[COMMIT seastar master] seastar/coroutine: drop std-coroutine.hh

4 views
Skip to first unread message

Commit Bot

<bot@cloudius-systems.com>
unread,
Jan 26, 2023, 4:55:32 AM1/26/23
to seastar-dev@googlegroups.com, Kefu Chai
From: Kefu Chai <kefu...@scylladb.com>
Committer: Avi Kivity <a...@scylladb.com>
Branch: master

seastar/coroutine: drop std-coroutine.hh

now that we only support the latest two major versions of GCC and
Clang, which are GCC {11,12} and Clang {14,15} respectively. all of
them support C++20 coroutines instead of coroutines-ts, which was
considered experimental before C++20 is officialy announced. and
before C++20, the coroutines header file was located at
`experimental/coroutine`, also we had to pass `-fcoroutines` or
`-fcoroutines-ts` to compiler to enable this feature explicitly.

but since C++20 coroutines is a part of C++20 standard, `-std=c++20`
enables C++20 coroutines. we don't need to detect it by checking
the compiler version or to check the existence of
`experimental/coroutine` anymore, neither do we need to patch
the standard library for a working coroutines support.

so, in this change

* we don't detect the existence of `experimental/coroutine`
* we don't patch `std::experimental` to get the coroutines work

C++17 + coroutines support is intact, as both GCC-11 and Clang-14
support C++20 coroutines if `-fcoroutines` or `-fcoroutines-ts` is
passed to in command line options when compiling in C++17 mode.

Signed-off-by: Kefu Chai <kefu...@scylladb.com>

---
diff --git a/include/seastar/core/condition-variable.hh b/include/seastar/core/condition-variable.hh
--- a/include/seastar/core/condition-variable.hh
+++ b/include/seastar/core/condition-variable.hh
@@ -92,7 +92,7 @@ private:

#ifdef SEASTAR_COROUTINES_ENABLED
struct [[nodiscard("must co_await a when() call")]] awaiter : public waiter, private seastar::task {
- using handle_type = SEASTAR_INTERNAL_COROUTINE_NAMESPACE::coroutine_handle<void>;
+ using handle_type = std::coroutine_handle<void>;

condition_variable* _cv;
handle_type _when_ready;
@@ -107,7 +107,7 @@ private:
return _cv->check_and_consume_signal();
}
template<typename T>
- void await_suspend(SEASTAR_INTERNAL_COROUTINE_NAMESPACE::coroutine_handle<T> h) {
+ void await_suspend(std::coroutine_handle<T> h) {
_when_ready = h;
_waiting_task = &h.promise();
_cv->add_waiter(*this);
@@ -144,7 +144,7 @@ private:
, _timeout(timeout)
{}
template<typename T>
- void await_suspend(SEASTAR_INTERNAL_COROUTINE_NAMESPACE::coroutine_handle<T> h) {
+ void await_suspend(std::coroutine_handle<T> h) {
awaiter::await_suspend(std::move(h));
this->set_callback(std::bind(&waiter::timeout, this));
this->arm(_timeout);
diff --git a/include/seastar/core/coroutine.hh b/include/seastar/core/coroutine.hh
--- a/include/seastar/core/coroutine.hh
+++ b/include/seastar/core/coroutine.hh
@@ -27,8 +27,8 @@
#error Coroutines support disabled.
#endif

-#include <seastar/core/std-coroutine.hh>
#include <seastar/coroutine/exception.hh>
+#include <coroutine>

namespace seastar {

@@ -70,11 +70,11 @@ public:
return _promise.get_future();
}

- SEASTAR_INTERNAL_COROUTINE_NAMESPACE::suspend_never initial_suspend() noexcept { return { }; }
- SEASTAR_INTERNAL_COROUTINE_NAMESPACE::suspend_never final_suspend() noexcept { return { }; }
+ std::suspend_never initial_suspend() noexcept { return { }; }
+ std::suspend_never final_suspend() noexcept { return { }; }

virtual void run_and_dispose() noexcept override {
- auto handle = SEASTAR_INTERNAL_COROUTINE_NAMESPACE::coroutine_handle<promise_type>::from_promise(*this);
+ auto handle = std::coroutine_handle<promise_type>::from_promise(*this);
handle.resume();
}

@@ -112,11 +112,11 @@ public:
return _promise.get_future();
}

- SEASTAR_INTERNAL_COROUTINE_NAMESPACE::suspend_never initial_suspend() noexcept { return { }; }
- SEASTAR_INTERNAL_COROUTINE_NAMESPACE::suspend_never final_suspend() noexcept { return { }; }
+ std::suspend_never initial_suspend() noexcept { return { }; }
+ std::suspend_never final_suspend() noexcept { return { }; }

virtual void run_and_dispose() noexcept override {
- auto handle = SEASTAR_INTERNAL_COROUTINE_NAMESPACE::coroutine_handle<promise_type>::from_promise(*this);
+ auto handle = std::coroutine_handle<promise_type>::from_promise(*this);
handle.resume();
}

@@ -142,7 +142,7 @@ public:
}

template<typename U>
- void await_suspend(SEASTAR_INTERNAL_COROUTINE_NAMESPACE::coroutine_handle<U> hndl) noexcept {
+ void await_suspend(std::coroutine_handle<U> hndl) noexcept {
if (!CheckPreempt || !_future.available()) {
_future.set_coroutine(hndl.promise());
} else {
@@ -167,7 +167,7 @@ public:
}

template<typename U>
- void await_suspend(SEASTAR_INTERNAL_COROUTINE_NAMESPACE::coroutine_handle<U> hndl) noexcept {
+ void await_suspend(std::coroutine_handle<U> hndl) noexcept {
if (!CheckPreempt || !_future.available()) {
_future.set_coroutine(hndl.promise());
} else {
@@ -192,7 +192,7 @@ public:
}

template<typename U>
- void await_suspend(SEASTAR_INTERNAL_COROUTINE_NAMESPACE::coroutine_handle<U> hndl) noexcept {
+ void await_suspend(std::coroutine_handle<U> hndl) noexcept {
if (!CheckPreempt || !_future.available()) {
_future.set_coroutine(hndl.promise());
} else {
@@ -273,11 +273,11 @@ auto operator co_await(coroutine::without_preemption_check<T...> f) noexcept {
} // seastar


-namespace SEASTAR_INTERNAL_COROUTINE_NAMESPACE {
+namespace std {

template<typename... T, typename... Args>
class coroutine_traits<seastar::future<T...>, Args...> : public seastar::internal::coroutine_traits_base<T...> {
};

-} // SEASTAR_INTERNAL_COROUTINE_NAMESPACE
+} // std

diff --git a/include/seastar/core/std-coroutine.hh b/include/seastar/core/std-coroutine.hh
--- a/include/seastar/core/std-coroutine.hh
+++ b/include/seastar/core/std-coroutine.hh
@@ -1,175 +0,0 @@
-/*
- * This file is open source software, licensed to you under the terms
- * of the Apache License, Version 2.0 (the "License"). See the NOTICE file
- * distributed with this work for additional information regarding copyright
- * ownership. You may not use this file except in compliance with the License.
- *
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-/*
- * Copyright (C) 2019 ScyllaDB Ltd.
- */
-
-#pragma once
-
-// Clang < 14 only supports the TS
-#if __has_include(<coroutine>) && (!defined(__clang__) || __clang_major__ >= 14)
-#include <coroutine>
-#define SEASTAR_INTERNAL_COROUTINE_NAMESPACE std
-#elif __has_include(<experimental/coroutine>)
-#include <experimental/coroutine>
-#define SEASTAR_INTERNAL_COROUTINE_NAMESPACE std::experimental
-#else
-#define SEASTAR_INTERNAL_COROUTINE_NAMESPACE std::experimental
-
-// We are not exactly allowed to defined anything in the std namespace, but this
-// makes coroutines work with libstdc++. All of this is experimental anyway.
-
-namespace std::experimental {
-
-template<typename Promise = void>
-class coroutine_handle {
- void* _pointer = nullptr;
-public:
- coroutine_handle() = default;
-
- coroutine_handle &operator=(nullptr_t) noexcept {
- _pointer = nullptr;
- return *this;
- }
-
- explicit operator bool() const noexcept { return _pointer; }
-
- static coroutine_handle from_address(void* ptr) noexcept {
- coroutine_handle hndl;
- hndl._pointer =ptr;
- return hndl;
- }
- void* address() const noexcept { return _pointer; }
-
- static coroutine_handle from_promise(Promise& promise) noexcept {
- coroutine_handle hndl;
- hndl._pointer = __builtin_coro_promise(&promise, alignof(Promise), true);
- return hndl;
- }
- Promise& promise() const noexcept {
- return *reinterpret_cast<Promise*>(__builtin_coro_promise(_pointer, alignof(Promise), false));
- }
-
- void operator()() noexcept { resume(); }
-
- void resume() const noexcept { __builtin_coro_resume(_pointer); }
- void destroy() const noexcept { __builtin_coro_destroy(_pointer); }
- bool done() const noexcept { return __builtin_coro_done(_pointer); }
-
- operator coroutine_handle<>() const noexcept;
-};
-
-template<>
-class coroutine_handle<void> {
- void* _pointer = nullptr;
-public:
- coroutine_handle() = default;
-
- coroutine_handle &operator=(nullptr_t) noexcept {
- _pointer = nullptr;
- return *this;
- }
-
- explicit operator bool() const noexcept { return _pointer; }
-
- static coroutine_handle from_address(void* ptr) noexcept {
- coroutine_handle hndl;
- hndl._pointer = ptr;
- return hndl;
- }
- void* address() const noexcept { return _pointer; }
-
- void operator()() noexcept { resume(); }
-
- void resume() const noexcept { __builtin_coro_resume(_pointer); }
- void destroy() const noexcept { __builtin_coro_destroy(_pointer); }
- bool done() const noexcept { return __builtin_coro_done(_pointer); }
-};
-
-struct noop_coroutine_promise { };
-
-template <>
-struct coroutine_handle<noop_coroutine_promise> {
- constexpr operator coroutine_handle<>() const noexcept {
- return coroutine_handle<>::from_address(address());
- }
-
- constexpr explicit operator bool() const noexcept { return true; }
-
- constexpr void* address() const noexcept { return _pointer; }
-
- constexpr bool done() const noexcept { return false; }
-
- void operator()() const noexcept { }
-
- void resume() const noexcept { }
-
- void destroy() const noexcept { }
-
- noop_coroutine_promise& promise() const noexcept {
- auto* p = __builtin_coro_promise(_pointer, alignof(noop_coroutine_promise), false);
- return *static_cast<noop_coroutine_promise*>(p);
- }
-
-private:
- friend coroutine_handle<noop_coroutine_promise> noop_coroutine() noexcept;
-
- coroutine_handle() noexcept = default;
-
- static struct {
- private:
- static void dummy_resume_destroy() { }
- public:
- void (*resume)() = dummy_resume_destroy;
- void (*destroy)() = dummy_resume_destroy;
- struct noop_coroutine_promise _p;
- } _frame;
- void *_pointer = &_frame;
-};
-
-using noop_coroutine_handle = coroutine_handle<noop_coroutine_promise>;
-
-inline noop_coroutine_handle noop_coroutine() noexcept {
- return {};
-}
-
-struct suspend_never {
- constexpr bool await_ready() const noexcept { return true; }
- template<typename T>
- constexpr void await_suspend(coroutine_handle<T>) noexcept { }
- constexpr void await_resume() noexcept { }
-};
-
-struct suspend_always {
- constexpr bool await_ready() const noexcept { return false; }
- template<typename T>
- constexpr void await_suspend(coroutine_handle<T>) noexcept { }
- constexpr void await_resume() noexcept { }
-};
-
-template <typename Promise>
-coroutine_handle<Promise>::operator coroutine_handle<>() const noexcept {
- return coroutine_handle<>::from_address(address());
-}
-
-template<typename T, typename... Args>
-class coroutine_traits { };
-
-}
-
-#endif
diff --git a/include/seastar/coroutine/all.hh b/include/seastar/coroutine/all.hh
--- a/include/seastar/coroutine/all.hh
+++ b/include/seastar/coroutine/all.hh
@@ -146,7 +146,7 @@ class [[nodiscard("must co_await an all() object")]] all {
using type = std::byte[std::max({sizeof(intermediate_task<idx>)...})];
};
using continuation_storage = generate_aligned_union<std::make_index_sequence<std::tuple_size_v<tuple>>>;
- using coroutine_handle_t = SEASTAR_INTERNAL_COROUTINE_NAMESPACE::coroutine_handle<void>;
+ using coroutine_handle_t = std::coroutine_handle<void>;
private:
tuple _futures;
private:
diff --git a/include/seastar/coroutine/as_future.hh b/include/seastar/coroutine/as_future.hh
--- a/include/seastar/coroutine/as_future.hh
+++ b/include/seastar/coroutine/as_future.hh
@@ -42,7 +42,7 @@ public:
}

template<typename U>
- void await_suspend(SEASTAR_INTERNAL_COROUTINE_NAMESPACE::coroutine_handle<U> hndl) noexcept {
+ void await_suspend(std::coroutine_handle<U> hndl) noexcept {
if (!CheckPreempt || !_future.available()) {
_future.set_coroutine(hndl.promise());
} else {
diff --git a/include/seastar/coroutine/exception.hh b/include/seastar/coroutine/exception.hh
--- a/include/seastar/coroutine/exception.hh
+++ b/include/seastar/coroutine/exception.hh
@@ -22,6 +22,7 @@
#pragma once

#include <seastar/core/coroutine.hh>
+#include <coroutine>

namespace seastar {

@@ -40,7 +41,7 @@ struct exception_awaiter {
}

template<typename U>
- void await_suspend(SEASTAR_INTERNAL_COROUTINE_NAMESPACE::coroutine_handle<U> hndl) noexcept {
+ void await_suspend(std::coroutine_handle<U> hndl) noexcept {
hndl.promise().set_exception(std::move(eptr));
hndl.destroy();
}
diff --git a/include/seastar/coroutine/generator.hh b/include/seastar/coroutine/generator.hh
--- a/include/seastar/coroutine/generator.hh
+++ b/include/seastar/coroutine/generator.hh
@@ -25,7 +25,6 @@
#include <optional>
#include <utility>
#include <seastar/core/future.hh>
-#include <seastar/core/std-coroutine.hh>
#include <seastar/util/attribute-compat.hh>

namespace seastar::coroutine::experimental {
@@ -47,11 +46,11 @@ enum class buffer_size_t : size_t;

namespace internal {

-using SEASTAR_INTERNAL_COROUTINE_NAMESPACE::coroutine_handle;
-using SEASTAR_INTERNAL_COROUTINE_NAMESPACE::suspend_never;
-using SEASTAR_INTERNAL_COROUTINE_NAMESPACE::suspend_always;
-using SEASTAR_INTERNAL_COROUTINE_NAMESPACE::suspend_never;
-using SEASTAR_INTERNAL_COROUTINE_NAMESPACE::noop_coroutine;
+using std::coroutine_handle;
+using std::suspend_never;
+using std::suspend_always;
+using std::suspend_never;
+using std::noop_coroutine;

template<typename T>
using next_value_t = std::optional<T>;
diff --git a/include/seastar/coroutine/maybe_yield.hh b/include/seastar/coroutine/maybe_yield.hh
--- a/include/seastar/coroutine/maybe_yield.hh
+++ b/include/seastar/coroutine/maybe_yield.hh
@@ -30,7 +30,7 @@ namespace seastar::coroutine {
namespace internal {

struct maybe_yield_awaiter final : task {
- using coroutine_handle_t = SEASTAR_INTERNAL_COROUTINE_NAMESPACE::coroutine_handle<void>;
+ using coroutine_handle_t = std::coroutine_handle<void>;

coroutine_handle_t when_ready;
task* main_coroutine_task;
@@ -40,7 +40,7 @@ struct maybe_yield_awaiter final : task {
}

template <typename T>
- void await_suspend(SEASTAR_INTERNAL_COROUTINE_NAMESPACE::coroutine_handle<T> h) {
+ void await_suspend(std::coroutine_handle<T> h) {
when_ready = h;
main_coroutine_task = &h.promise(); // for waiting_task()
schedule(this);
diff --git a/include/seastar/coroutine/parallel_for_each.hh b/include/seastar/coroutine/parallel_for_each.hh
--- a/include/seastar/coroutine/parallel_for_each.hh
+++ b/include/seastar/coroutine/parallel_for_each.hh
@@ -60,7 +60,7 @@ namespace seastar::coroutine {
template <typename Func>
// constaints for Func are defined at the parallel_for_each constructor
class [[nodiscard("must co_await an parallel_for_each() object")]] parallel_for_each final : continuation_base<> {
- using coroutine_handle_t = SEASTAR_INTERNAL_COROUTINE_NAMESPACE::coroutine_handle<void>;
+ using coroutine_handle_t = std::coroutine_handle<void>;

Func _func;
boost::container::small_vector<future<>, 5> _futures;
@@ -151,7 +151,7 @@ public:
}

template<typename T>
- void await_suspend(SEASTAR_INTERNAL_COROUTINE_NAMESPACE::coroutine_handle<T> h) {
+ void await_suspend(std::coroutine_handle<T> h) {
_when_ready = h;
_waiting_task = &h.promise();
resume_or_set_callback();
diff --git a/include/seastar/coroutine/switch_to.hh b/include/seastar/coroutine/switch_to.hh
--- a/include/seastar/coroutine/switch_to.hh
+++ b/include/seastar/coroutine/switch_to.hh
@@ -70,7 +70,7 @@ public:
}

template<typename T>
- void await_suspend(SEASTAR_INTERNAL_COROUTINE_NAMESPACE::coroutine_handle<T> hndl) noexcept {
+ void await_suspend(std::coroutine_handle<T> hndl) noexcept {
auto& t = hndl.promise();
t.set_scheduling_group(_switch_to_sg);
_task = &t;
diff --git a/include/seastar/util/std-compat.hh b/include/seastar/util/std-compat.hh
--- a/include/seastar/util/std-compat.hh
+++ b/include/seastar/util/std-compat.hh
@@ -37,7 +37,11 @@ namespace std::pmr {
#endif

#if defined(__cpp_impl_coroutine) || defined(__cpp_coroutines)
+#if __has_include(<coroutine>)
#define SEASTAR_COROUTINES_ENABLED
+#else
+#error Please use a C++ compiler with C++20 coroutines support
+#endif
#endif

// Defining SEASTAR_ASAN_ENABLED in here is a bit of a hack, but
Reply all
Reply to author
Forward
0 new messages