| // <coroutine> -*- C++ -*- |
| |
| // Copyright (C) 2019-2020 Free Software Foundation, Inc. |
| // |
| // This file is part of the GNU ISO C++ Library. This library is free |
| // software; you can redistribute it and/or modify it under the |
| // terms of the GNU General Public License as published by the |
| // Free Software Foundation; either version 3, or (at your option) |
| // any later version. |
| |
| // This library is distributed in the hope that it will be useful, |
| // but WITHOUT ANY WARRANTY; without even the implied warranty of |
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| // GNU General Public License for more details. |
| |
| // Under Section 7 of GPL version 3, you are granted additional |
| // permissions described in the GCC Runtime Library Exception, version |
| // 3.1, as published by the Free Software Foundation. |
| |
| // You should have received a copy of the GNU General Public License and |
| // a copy of the GCC Runtime Library Exception along with this program; |
| // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
| // <http://www.gnu.org/licenses/>. |
| |
| /** @file include/coroutine |
| * This is a Standard C++ Library header. |
| */ |
| |
| #ifndef _GLIBCXX_COROUTINE |
| #define _GLIBCXX_COROUTINE 1 |
| |
| #pragma GCC system_header |
| |
| // It is very likely that earlier versions would work, but they are untested. |
| #if __cplusplus >= 201402L |
| |
| #include <bits/c++config.h> |
| |
| /** |
| * @defgroup coroutines Coroutines |
| * |
| * Components for supporting coroutine implementations. |
| */ |
| |
| #if __cplusplus > 201703L && __cpp_impl_three_way_comparison >= 201907L |
| # include <compare> |
| # define _COROUTINES_USE_SPACESHIP 1 |
| #else |
| # include <bits/stl_function.h> // for std::less |
| # define _COROUTINES_USE_SPACESHIP 0 |
| #endif |
| |
| namespace std _GLIBCXX_VISIBILITY (default) |
| { |
| _GLIBCXX_BEGIN_NAMESPACE_VERSION |
| |
| #if __cpp_impl_coroutine |
| |
| #define __cpp_lib_coroutine 201902L |
| |
| inline namespace __n4861 { |
| |
| // 17.12.2 coroutine traits |
| /// [coroutine.traits] |
| /// [coroutine.traits.primary] |
| /// If _Result::promise_type is valid and denotes a type then the traits |
| /// have a single publicly accessible member, otherwise they are empty. |
| template <typename _Result, typename = void> |
| struct __coroutine_traits_impl {}; |
| |
| template <typename _Result> |
| struct __coroutine_traits_impl<_Result, |
| __void_t<typename _Result::promise_type>> |
| { |
| using promise_type = typename _Result::promise_type; |
| }; |
| |
| template <typename _Result, typename...> |
| struct coroutine_traits : __coroutine_traits_impl<_Result> {}; |
| |
| // 17.12.3 Class template coroutine_handle |
| /// [coroutine.handle] |
| template <typename _Promise = void> |
| struct coroutine_handle; |
| |
| template <> struct |
| coroutine_handle<void> |
| { |
| public: |
| // 17.12.3.1, construct/reset |
| constexpr coroutine_handle() noexcept : _M_fr_ptr(0) {} |
| |
| constexpr coroutine_handle(std::nullptr_t __h) noexcept |
| : _M_fr_ptr(__h) |
| {} |
| |
| coroutine_handle& operator=(std::nullptr_t) noexcept |
| { |
| _M_fr_ptr = nullptr; |
| return *this; |
| } |
| |
| public: |
| // 17.12.3.2, export/import |
| constexpr void* address() const noexcept { return _M_fr_ptr; } |
| |
| constexpr static coroutine_handle from_address(void* __a) noexcept |
| { |
| coroutine_handle __self; |
| __self._M_fr_ptr = __a; |
| return __self; |
| } |
| |
| public: |
| // 17.12.3.3, observers |
| constexpr explicit operator bool() const noexcept |
| { |
| return bool(_M_fr_ptr); |
| } |
| |
| bool done() const noexcept { return __builtin_coro_done(_M_fr_ptr); } |
| |
| // 17.12.3.4, resumption |
| void operator()() const { resume(); } |
| |
| void resume() const { __builtin_coro_resume(_M_fr_ptr); } |
| |
| void destroy() const { __builtin_coro_destroy(_M_fr_ptr); } |
| |
| protected: |
| void* _M_fr_ptr; |
| }; |
| |
| // 17.12.3.6 Comparison operators |
| /// [coroutine.handle.compare] |
| constexpr bool operator==(coroutine_handle<> __a, |
| coroutine_handle<> __b) noexcept |
| { |
| return __a.address() == __b.address(); |
| } |
| |
| #if _COROUTINES_USE_SPACESHIP |
| constexpr strong_ordering |
| operator<=>(coroutine_handle<> __a, coroutine_handle<> __b) noexcept |
| { return std::compare_three_way()(__a.address(), __b.address()); } |
| #else |
| // These are to enable operation with std=c++14,17. |
| constexpr bool operator!=(coroutine_handle<> __a, |
| coroutine_handle<> __b) noexcept |
| { |
| return !(__a == __b); |
| } |
| |
| constexpr bool operator<(coroutine_handle<> __a, |
| coroutine_handle<> __b) noexcept |
| { |
| return less<void*>()(__a.address(), __b.address()); |
| } |
| |
| constexpr bool operator>(coroutine_handle<> __a, |
| coroutine_handle<> __b) noexcept |
| { |
| return __b < __a; |
| } |
| |
| constexpr bool operator<=(coroutine_handle<> __a, |
| coroutine_handle<> __b) noexcept |
| { |
| return !(__a > __b); |
| } |
| |
| constexpr bool operator>=(coroutine_handle<> __a, |
| coroutine_handle<> __b) noexcept |
| { |
| return !(__a < __b); |
| } |
| #endif |
| |
| template <typename _Promise> |
| struct coroutine_handle : coroutine_handle<> |
| { |
| // 17.12.3.1, construct/reset |
| using coroutine_handle<>::coroutine_handle; |
| |
| static coroutine_handle from_promise(_Promise& p) |
| { |
| coroutine_handle __self; |
| __self._M_fr_ptr |
| = __builtin_coro_promise((char*) &p, __alignof(_Promise), true); |
| return __self; |
| } |
| |
| coroutine_handle& operator=(std::nullptr_t) noexcept |
| { |
| coroutine_handle<>::operator=(nullptr); |
| return *this; |
| } |
| |
| // 17.12.3.2, export/import |
| constexpr static coroutine_handle from_address(void* __a) noexcept |
| { |
| coroutine_handle __self; |
| __self._M_fr_ptr = __a; |
| return __self; |
| } |
| |
| // 17.12.3.5, promise accesss |
| _Promise& promise() const |
| { |
| void* __t |
| = __builtin_coro_promise (this->_M_fr_ptr, __alignof(_Promise), false); |
| return *static_cast<_Promise*>(__t); |
| } |
| }; |
| |
| /// [coroutine.noop] |
| struct noop_coroutine_promise |
| { |
| }; |
| |
| void __dummy_resume_destroy() __attribute__((__weak__)); |
| void __dummy_resume_destroy() {} |
| |
| struct __noop_coro_frame |
| { |
| void (*__r)() = __dummy_resume_destroy; |
| void (*__d)() = __dummy_resume_destroy; |
| struct noop_coroutine_promise __p; |
| } __noop_coro_fr __attribute__((__weak__)); |
| |
| // 17.12.4.1 Class noop_coroutine_promise |
| /// [coroutine.promise.noop] |
| template <> |
| struct coroutine_handle<noop_coroutine_promise> : public coroutine_handle<> |
| { |
| using _Promise = noop_coroutine_promise; |
| |
| public: |
| // 17.12.4.2.1, observers |
| constexpr explicit operator bool() const noexcept { return true; } |
| |
| constexpr bool done() const noexcept { return false; } |
| |
| // 17.12.4.2.2, resumption |
| void operator()() const noexcept {} |
| |
| void resume() const noexcept {} |
| |
| void destroy() const noexcept {} |
| |
| // 17.12.4.2.3, promise access |
| _Promise& promise() const |
| { |
| return *static_cast<_Promise*>( |
| __builtin_coro_promise(this->_M_fr_ptr, __alignof(_Promise), false)); |
| } |
| |
| // 17.12.4.2.4, address |
| private: |
| friend coroutine_handle<noop_coroutine_promise> noop_coroutine() noexcept; |
| |
| coroutine_handle() noexcept { this->_M_fr_ptr = (void*) &__noop_coro_fr; } |
| }; |
| |
| using noop_coroutine_handle = coroutine_handle<noop_coroutine_promise>; |
| |
| inline noop_coroutine_handle noop_coroutine() noexcept |
| { |
| return noop_coroutine_handle(); |
| } |
| |
| // 17.12.5 Trivial awaitables |
| /// [coroutine.trivial.awaitables] |
| struct suspend_always |
| { |
| constexpr bool await_ready() const noexcept { return false; } |
| |
| constexpr void await_suspend(coroutine_handle<>) const noexcept {} |
| |
| constexpr void await_resume() const noexcept {} |
| }; |
| |
| struct suspend_never |
| { |
| constexpr bool await_ready() const noexcept { return true; } |
| |
| constexpr void await_suspend(coroutine_handle<>) const noexcept {} |
| |
| constexpr void await_resume() const noexcept {} |
| }; |
| |
| } // namespace __n4861 |
| |
| #else |
| #error "the coroutine header requires -fcoroutines" |
| #endif |
| |
| _GLIBCXX_END_NAMESPACE_VERSION |
| } // namespace std |
| |
| #endif // C++14 (we are allowing use from at least this) |
| |
| #endif // _GLIBCXX_COROUTINE |