Created
May 29, 2020 07:40
-
-
Save dascandy/20a0c890dc565f6fadffda0bd268f5b5 to your computer and use it in GitHub Desktop.
Freestanding experimental/coroutine
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #pragma once | |
| namespace std { | |
| template <typename T> struct remove_cv { using type = T; }; | |
| template <typename T> struct remove_cv<const T> { using type = T; }; | |
| template <typename T> struct remove_cv<volatile T> { using type = T; }; | |
| template <typename T> struct remove_cv<const volatile T> { using type = T; }; | |
| template <typename T> using remove_cv_t = typename remove_cv<T>::type; | |
| namespace experimental { | |
| template<typename R, typename... ArgTypes> | |
| struct coroutine_traits { | |
| using promise_type = typename R::promise_type; | |
| }; | |
| template<class Promise = void> | |
| struct coroutine_handle; | |
| template<> | |
| struct coroutine_handle<void> | |
| { | |
| constexpr coroutine_handle() noexcept | |
| : ptr(nullptr) | |
| { | |
| } | |
| constexpr coroutine_handle(nullptr_t) noexcept | |
| : ptr(nullptr) | |
| { | |
| } | |
| coroutine_handle& operator=(nullptr_t) noexcept { | |
| ptr = nullptr; | |
| return *this; | |
| } | |
| constexpr void* address() const noexcept { | |
| return ptr; | |
| } | |
| static constexpr coroutine_handle from_address(void* addr) { | |
| return coroutine_handle{addr}; | |
| } | |
| constexpr explicit operator bool() const noexcept { | |
| return ptr != nullptr; | |
| } | |
| bool done() const; | |
| void operator()() const; | |
| void resume() const { | |
| __builtin_coro_resume(ptr); | |
| } | |
| void destroy() const; | |
| public: | |
| constexpr coroutine_handle(void* p) noexcept | |
| : ptr(p) | |
| {} | |
| void* ptr; | |
| }; | |
| template<class Promise> | |
| struct coroutine_handle : coroutine_handle<> | |
| { | |
| using coroutine_handle<>::coroutine_handle; | |
| static coroutine_handle from_promise(Promise&p) { | |
| using RawPromise = typename std::remove_cv_t<Promise>; | |
| coroutine_handle __tmp; | |
| __tmp.ptr = __builtin_coro_promise(&const_cast<RawPromise&>(p), alignof(Promise), true); | |
| return __tmp; | |
| } | |
| coroutine_handle& operator=(nullptr_t) noexcept { | |
| ptr = nullptr; | |
| return *this; | |
| } | |
| static constexpr coroutine_handle from_address(void* addr) { | |
| return coroutine_handle{addr}; | |
| } | |
| Promise& promise() const { | |
| } | |
| }; | |
| constexpr bool operator==(coroutine_handle<> x, coroutine_handle<> y) noexcept; | |
| // constexpr strong_ordering operator<=>(coroutine_handle<> x, coroutine_handle<> y) noexcept; | |
| template<class T> struct hash; | |
| template<class P> struct hash<coroutine_handle<P>>; | |
| struct noop_coroutine_promise; | |
| using noop_coroutine_handle = coroutine_handle<noop_coroutine_promise>; | |
| noop_coroutine_handle noop_coroutine() noexcept; | |
| struct suspend_never { | |
| bool await_ready() { | |
| return true; | |
| } | |
| void await_suspend(std::experimental::coroutine_handle<> awaiting) {} | |
| void await_resume() {} | |
| }; | |
| struct suspend_always { | |
| bool await_ready() { | |
| return false; | |
| } | |
| void await_suspend(std::experimental::coroutine_handle<> awaiting) {} | |
| void await_resume() {} | |
| }; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment