1 #include "coro.h"
2 
3 #include <exception>
4 #include <vector>
5 
6 template <typename T>
7 struct promise {
8   T _value;
9   coro::coroutine_handle<> _continuation = nullptr;
10 
11   struct final_awaitable {
12     bool _has_continuation;
final_awaitablepromise::final_awaitable13     final_awaitable(bool has_continuation)
14         : _has_continuation(has_continuation) {}
15 
await_readypromise::final_awaitable16     bool await_ready() const noexcept { return !_has_continuation; }
17 
18     template <typename Promise>
19     coro::coroutine_handle<>
await_suspendpromise::final_awaitable20     await_suspend(coro::coroutine_handle<Promise> coro) noexcept {
21       return coro.promise()._continuation;
22     }
23 
await_resumepromise::final_awaitable24     void await_resume() noexcept {}
25   };
26 
get_return_objectpromise27   auto get_return_object() noexcept {
28     return coro::coroutine_handle<promise>::from_promise(*this);
29   }
30 
initial_suspendpromise31   auto initial_suspend() noexcept { return coro::suspend_always(); }
32 
final_suspendpromise33   auto final_suspend() noexcept {
34     return final_awaitable(_continuation != nullptr);
35   }
36 
return_valuepromise37   void return_value(T value) { _value = value; }
38 
unhandled_exceptionpromise39   void unhandled_exception() { std::terminate(); }
40 };
41 
42 template <typename T>
43 struct task {
44   using promise_type = promise<T>;
45   std::coroutine_handle<promise<T>> _handle;
46 
tasktask47   task (coro::coroutine_handle<promise<T>> handle) : _handle(handle) {}
48 #if DELETE_COPY_CTOR
49  task (const task &) = delete; // no copying
50 #endif
51 #if DELETE_MOVE_CTOR
tasktask52  task(task&& t) noexcept
53     : _handle(t._handle) { t._handle = nullptr; }
54 #endif
await_readytask55   bool await_ready() noexcept { return _handle.done(); }
56 
57   std::coroutine_handle<>
await_suspendtask58   await_suspend(std::coroutine_handle<> handle) noexcept {
59     _handle.promise()._continuation = handle;
60     return _handle;
61   }
62 
await_resumetask63   T await_resume() noexcept { return _handle.promise()._value; }
64 };
65