1 #include <iostream> 2 #include <exception> 3 #include <cassert> 4 5 #if __has_include("coroutine") 6 #include <coroutine> 7 namespace stdcoro = std; 8 #else 9 #include <experimental/coroutine> 10 namespace stdcoro = std::experimental; 11 #endif 12 13 struct footable : stdcoro::suspend_always { 14 footable() noexcept = default; ~footablefootable15 ~footable() { assert(released); } 16 footable(const footable&) = delete; 17 18 using coro_handle = stdcoro::coroutine_handle<>; 19 await_suspendfootable20 void await_suspend(coro_handle awaiter) noexcept { 21 std::cout << "suspending to footable " << this << std::endl; 22 assert(!handle); 23 handle = awaiter; 24 } await_resumefootable25 void await_resume() noexcept { 26 std::cout << "resuming from footable " << this << std::endl; 27 assert(handle); 28 handle = {}; 29 } 30 operatorfootable31 void operator()() noexcept { 32 std::cout << "operator() on " << this << std::endl; 33 assert(handle); 34 handle.resume(); 35 handle = {}; 36 } 37 releasefootable38 void release() noexcept { released = true; } 39 private: 40 coro_handle handle; 41 bool released = false; 42 }; 43 44 struct footask { 45 struct promise_type { 46 using coro_handle = stdcoro::coroutine_handle<promise_type>; 47 initial_suspendfootask::promise_type48 stdcoro::suspend_never initial_suspend() noexcept { return {}; } final_suspendfootask::promise_type49 stdcoro::suspend_never final_suspend() noexcept { std::cout << "final suspend" << std::endl; return {}; } unhandled_exceptionfootask::promise_type50 void unhandled_exception() {} return_voidfootask::promise_type51 void return_void() noexcept { std::cout << "coro returns" << std::endl; } 52 get_return_objectfootask::promise_type53 footask get_return_object() { return footask{ coro_handle::from_promise(*this) }; } 54 }; 55 footaskfootask56 footask(promise_type::coro_handle handle) : handle(handle) {} ~footaskfootask57 ~footask() { assert(handle.done()); } 58 59 promise_type::coro_handle handle; 60 }; 61 62 struct bar { 63 bar() = default; 64 bar(const bar&) = delete; 65 66 footable foo{}; 67 footask task = taskfun(); 68 taskfunbar69 footask taskfun() noexcept { 70 std::cout << "coro begin" << std::endl; 71 co_await foo; 72 std::cout << "coro end" << std::endl; 73 } 74 }; 75 main()76int main() { 77 bar foobar; 78 foobar.foo(); 79 assert(foobar.task.handle.done()); 80 std::cout << "releasing" << std::endl; 81 foobar.foo.release(); 82 std::cout << "done" << std::endl; 83 return 0; 84 } 85