task get_return_object(){ std::cout << "2.create coroutine return object, and the coroutine is created now\n"; return {std::coroutine_handle<task::promise_type>::from_promise(*this)};}
std::suspend_never initial_suspend(){ std::cout << "3.do you want to suspend the current coroutine?\n"; std::cout << "4.don't suspend because return std::suspend_never, so continue to execute coroutine body\n"; return {};}
std::suspend_never final_suspend()noexcept{ std::cout << "13.coroutine body finished, do you want to suspend the current coroutine?\n"; std::cout << "14.don't suspend because return std::suspend_never, and the coroutine will be automatically destroyed, bye\n"; return {};}
voidreturn_void(){ std::cout << "12.coroutine doesn't return value, so return_void is called\n";}
如果协程不返回值(使用 co_return),这个函数会被调用。
3.6 unhandled_exception()
voidunhandled_exception(){}
这个函数在协程中发生未处理的异常时被调用。
4. 协程的挂起与恢复:awaiter 详解
协程通过 co_await 来挂起和恢复。awaiter 是实现协程挂起的关键。
4.1 await_ready()
boolawait_ready(){ std::cout << "6.do you want to suspend current coroutine?\n"; std::cout << "7.yes, suspend because awaiter.await_ready() return false\n"; returnfalse;}
这个函数决定协程是否立即挂起。返回 false 表示协程需要挂起。
4.2 await_suspend()
voidawait_suspend(std::coroutine_handle<task::promise_type> handle){ std::cout << "8.execute awaiter.await_suspend()\n"; std::thread([handle]() mutable { handle(); }).detach(); std::cout << "9.a new thread launched, and will return back to caller\n";}
这个函数在协程需要挂起时被调用。它启动一个新的线程来恢复协程的执行。
4.3 await_resume()
voidawait_resume(){}
这个函数在协程恢复执行时被调用。
5. 代码执行流程详解
让我们详细分析一下提供的代码的执行流程:
5.1 完整代码
#include<coroutine>#include<iostream>#include<thread>namespace Coroutine {
structtask {
structpromise_type {
promise_type(){ std::cout << "1.create promise object\n"; }
task get_return_object(){
std::cout << "2.create coroutine return object, and the coroutine is created now\n";
return {std::coroutine_handle<task::promise_type>::from_promise(*this)};
}
std::suspend_never initial_suspend(){
std::cout << "3.do you want to suspend the current coroutine?\n";
std::cout << "4.don't suspend because return std::suspend_never, so continue to execute coroutine body\n";
return {};
}
std::suspend_never final_suspend()noexcept{
std::cout << "13.coroutine body finished, do you want to suspend the current coroutine?\n";
std::cout << "14.don't suspend because return std::suspend_never, and the coroutine will be automatically destroyed, bye\n";
return {};
}
voidreturn_void(){ std::cout << "12.coroutine doesn't return value, so return_void is called\n"; }
voidunhandled_exception(){}
};
std::coroutine_handle<task::promise_type> handle_;
};
structawaiter {
boolawait_ready(){
std::cout << "6.do you want to suspend current coroutine?\n";
std::cout << "7.yes, suspend because awaiter.await_ready() return false\n";
returnfalse;
}
voidawait_suspend(std::coroutine_handle<task::promise_type> handle){
std::cout << "8.execute awaiter.await_suspend()\n";
std::thread([handle]() mutable { handle(); }).detach();
std::cout << "9.a new thread launched, and will return back to caller\n";
}
voidawait_resume(){}
};
task test(){
std::cout << "5.begin to execute coroutine body, the thread\n";
// co_await awaiter{};
std::cout << "11.coroutine resumed, continue execute coroutine body now, the thread\n";
}
} // namespace Coroutineintmain(){
Coroutine::test();
std::cout << "10.come back to caller because of co_await awaiter\n";
std::this_thread::sleep_for(std::chrono::seconds(1));
return0;
}
5.2 执行结果
1.create promise object2.create coroutine returnobject, and the coroutine is created now
3.do you want to suspend the current coroutine?
4.don't suspend because return std::suspend_never, so continue to execute coroutine body5.begin to execute coroutine body, the thread id=0x7f8e2d7e0700
6.do you want to suspend current coroutine?
7.yes, suspend because awaiter.await_ready() returnfalse8.execute awaiter.await_suspend()
9.a new thread launched, and will return back to caller
10.come back to caller because of co_await awaiter
11.coroutine resumed, continue execute coroutine body now, the thread id=0x7f8e2d7e0700
12.coroutine doesn't return value, so return_void is called13.coroutine body finished, do you want to suspend the current coroutine?
14.don't suspend because return std::suspend_never, and the coroutine will be automatically destroyed, bye
structFibonacci {
structpromise_type {// ...}// ...
};
Fibonacci fib(){
int a = 0, b = 1;
co_yield a;
co_yield b;
while(true){
int c = a + b; a = b; b = c;
co_yield c;
}
}