| 10 | |
| 11 | template<class T> |
| 12 | struct task |
| 13 | { |
| 14 | struct promise_type |
| 15 | { |
| 16 | auto get_return_object() |
| 17 | { |
| 18 | return task(std::coroutine_handle<promise_type>::from_promise(*this)); |
| 19 | } |
| 20 | std::suspend_always initial_suspend() { return {}; } |
| 21 | struct final_awaiter |
| 22 | { |
| 23 | bool await_ready() noexcept { return false; } |
| 24 | void await_resume() noexcept {} |
| 25 | std::coroutine_handle<> |
| 26 | await_suspend(std::coroutine_handle<promise_type> h) noexcept |
| 27 | { |
| 28 | // final_awaiter::await_suspend is called when the execution of the |
| 29 | // current coroutine (referred to by 'h') is about to finish. |
| 30 | // If the current coroutine was resumed by another coroutine via |
| 31 | // co_await get_task(), a handle to that coroutine has been stored |
| 32 | // as h.promise().previous. In that case, return the handle to resume |
| 33 | // the previous coroutine. |
| 34 | // Otherwise, return noop_coroutine(), whose resumption does nothing. |
| 35 | |
| 36 | if (auto previous = h.promise().previous; previous) |
| 37 | return previous; |
| 38 | else |
| 39 | return std::noop_coroutine(); |
| 40 | } |
| 41 | }; |
| 42 | final_awaiter final_suspend() noexcept { return {}; } |
| 43 | void unhandled_exception() { throw; } |
| 44 | void return_value(T value) { result = std::move(value); } |
| 45 | |
| 46 | T result; |
| 47 | std::coroutine_handle<> previous; |
| 48 | }; |
| 49 | |
| 50 | task(std::coroutine_handle<promise_type> h) : coro(h) {} |
| 51 | task(task&& t) = default; |
| 52 | task& operator=(task&& t) = default; |
| 53 | ~task() { coro.destroy(); } |
| 54 | |
| 55 | struct awaiter |
| 56 | { |
| 57 | bool await_ready() { return false; } |
| 58 | T await_resume() { return std::move(coro.promise().result); } |
| 59 | auto await_suspend(std::coroutine_handle<> h) |
| 60 | { |
| 61 | coro.promise().previous = h; |
| 62 | return coro; |
| 63 | } |
| 64 | std::coroutine_handle<promise_type> coro; |
| 65 | }; |
| 66 | awaiter operator co_await() { return awaiter{coro}; } |
| 67 | T operator()() |
| 68 | { |
| 69 | coro.resume(); |
no outgoing calls