C++20协程异步
code
#include <coroutine>
#include <future>
#include <iostream>
#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 faultreturn 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<promise_type>::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<promise_type> 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