coro.cpp (2640B)
1 #include "linux.hpp" 2 3 namespace std 4 { 5 6 template <typename T, typename... Ts> 7 struct coroutine_traits 8 { 9 using promise_type = T::promise_type; 10 }; 11 12 template <typename T = void> 13 struct coroutine_handle { 14 static coroutine_handle from_address(void* ptr) noexcept 15 { 16 return coroutine_handle{ptr}; 17 } 18 static coroutine_handle from_promise(T& promise) noexcept 19 { 20 return from_address(reinterpret_cast<char*>(&promise) - sizeof(frame)); 21 } 22 void resume() const noexcept { 23 assert(fp); 24 assert(fp->resume); 25 fp->resume(fp); 26 } 27 void destroy() const noexcept { 28 assert(fp); 29 assert(fp->destroy); 30 fp->destroy(fp); 31 } 32 bool done() const noexcept 33 { 34 assert(fp); 35 return not fp->resume; 36 } 37 38 private: 39 struct frame 40 { 41 void(*resume)(frame*) noexcept; 42 void(*destroy)(frame*) noexcept; 43 }; 44 45 coroutine_handle(void* ptr) noexcept : fp{reinterpret_cast<frame*>(ptr)} {} 46 frame* fp = nullptr; 47 }; 48 49 struct suspend_always 50 { 51 bool await_ready() noexcept { return false; } 52 template <typename T> // easier to make this a template method than provide a <void> specialisation to coroutine_handle for now 53 void await_suspend(coroutine_handle<T>) noexcept {} 54 void await_resume() noexcept {} 55 }; 56 57 struct suspend_never 58 { 59 bool await_ready() noexcept { return true; } 60 template <typename T> 61 void await_suspend(coroutine_handle<T>) noexcept { __builtin_trap(); } 62 void await_resume() noexcept {} 63 }; 64 65 } 66 67 struct task 68 { 69 struct promise_type { 70 std::suspend_never initial_suspend() noexcept { return {}; } 71 std::suspend_always final_suspend() noexcept { return {}; } 72 task get_return_object() noexcept { return {*this}; } 73 void unhandled_exception() noexcept {} 74 void return_void() noexcept {} 75 void* operator new(size_t s, span<char> storage) noexcept { 76 assert(s <= storage.size()); 77 return storage.begin(); 78 } 79 void operator delete(void*, size_t) noexcept {} 80 }; 81 82 ~task() { h.destroy(); } 83 bool done() const noexcept { return h.done(); } 84 void resume() const noexcept { h.resume(); } 85 private: 86 friend struct promise_type; 87 task(promise_type& p) : h{decltype(h)::from_promise(p)} {} 88 std::coroutine_handle<promise_type> h; 89 }; 90 91 task mytask(span<char> /*forwarded to new*/) noexcept 92 { 93 *write(stdout, "mytask: started\n"_sp); 94 for (int i = 0; i < 3; ++i) 95 { 96 co_await std::suspend_always{}; 97 *write(stdout, "mytask: resumed\n"_sp); 98 } 99 co_return; 100 } 101 102 int main() 103 { 104 *write(stdout, "main\n"_sp); 105 { 106 char memory[56]; 107 task t = mytask(span{memory}); 108 *write(stdout, "main: mytask created\n"_sp); 109 while (not t.done()) 110 { 111 t.resume(); 112 *write(stdout, "main: back from resume\n"_sp); 113 } 114 } 115 *write(stdout, "main: mytask destroyed\n"_sp); 116 }