> 技术文档 > C++20协程异步

C++20协程异步


code
#include #include #include #include \"QApplication.h\"/* * 自定义协程等待体 */struct MyWaiter { int value; constexpr bool await_ready() const noexcept { std::cout << \"Step 5\\n\"; return false; // true=准备好了不挂起,false=挂起 } bool await_suspend(std::coroutine_handle handle) { // 协程挂起时调用 // 切换线程 std::cout << \"Step 6\\n\"; std::async([=] {std::cout << \"Step 7\\n\"; std::this_thread::sleep_for(std::chrono::seconds(1)); handle.resume(); // 延迟1s后恢复协程 }); std::cout << \"Step 11\\n\"; return true; // 挂起 } int await_resume() { // 协程恢复时调用 std::cout << \"Step 8\\n\"; return value; }};/* * 自定义返回值 * 需要开发者自行保证协程在挂起后续恢复执行时参数引用或者指针指向的对象仍然存活 * */struct GenIntIter { struct promise_type { int value_; promise_type() { std::cout << \"Step 1\\n\"; } GenIntIter get_return_object() { std::cout << \"Step 2\\n\"; return GenIntIter { *this }; } static GenIntIter get_return_object_on_allocation_failure() { // new 分配失败 promise_type result; result.value_ = -1; return GenIntIter(result); } auto initial_suspend() const noexcept { // 运行前 std::cout << \"Step 3\\n\"; return std::suspend_never {}; // 挂起 // return MyWaiter { .value = value_ }; } auto final_suspend() const noexcept { // 析构前std::cout << \"Step 10\\n\"; // 如果在 final_suspend 那里停下,手动调用 coro.destroy(),不然就会漏内存 // 如果已经final_suspend了,再coro.destroy()会seg fault return std::suspend_always {}; // 挂起 // return std::suspend_never {}; // 不挂起 } auto yield_value(int value) { value_ = value; return std::suspend_always {}; // 挂起 } void return_value(int value) { value_ = value; } void unhandled_exception() { std::terminate(); } }; explicit GenIntIter(promise_type& p) : handle_(std::coroutine_handle::from_promise(p)) { } ~GenIntIter() { if (handle_ && !handle_.done()) handle_.destroy(); } int next() { if (!handle_ || handle_.done()) return -1; handle_(); return handle_.promise().value_; } int val() { return handle_.promise().value_; } std::coroutine_handle handle_;};// 协程函数GenIntIter foo(){ for (int i = 0; i < 10; ++i) { co_yield i; } co_return -1;}int work(){ return 5;}// 线程异步void thread(){ auto n = std::async(work); n.wait();}// 协程异步GenIntIter corioutine(int val){ std::cout << \"Step 4\\n\"; auto n = co_await MyWaiter { .value = val }; std::cout << \"Step 9\\n\"; co_return n;}int main(int argc, char** argv){ corioutine(5); std::cout << \"Step 12\\n\"; // 当 caller 调用一个协程的时候会先创建一个协程帧 // 协程帧会构建 promise 对象, // 再通过 promise对象产生 return object。 auto handle = foo(); do { handle.val(); } while (-1 != handle.next()); QApplication app(argc, argv); return app.run;}
参考

https://zhuanlan.zhihu.com/p/657993277

https://github.com/tearshark/librf

https://github.com/naasking/async.h

https://github.com/xiaoliang314/libatask/tree/master/lib