我们来剖析一下协程的过程。通过这个剖析,希望达到梳理协程几个重要概念的关系,把这些点串起来。所以在概念参考我们列出了相应的概念文字。,C++20协程在启动前,开始会new 一个协程状态(coroutine state)。然后构造协程的承诺对象(promise)。承诺对象(promise)通过get_return_object()构造协程的返回值result。这个返回值在协程第一次挂起时,赋值给调用者。然后通过co_await promise.initial_suspend(),决定协程初试完成后的行为。如果返回std::suspend_always,初始化就挂起,如果返回std::suspend_never ,初始化后就继续运行。(注意initial_suspend也可以返回其他协程体),
,cw_ret = co_await awaiter 或者cw_ret = co_await fun(),先计算表达式fun,fun返回结果,就是一个等待体awaiter。系统先调用awaiter.await_ready()接口,看等待体是否准备好了,没准备好(return false)就调用awaiter.await_suspend()。await_suspend根据参数可以记录调用其的协程的的句柄。await_suspend的返回值为return true ,或者 return void 就会挂起协程。,后面在外部如果恢复了协程的运行,awaiter.await_resume()接口被调用。其返回结果,作为co_await的返回值。,
,co_yield cy_ret;,相当于调用co_wait promise.yield_value(cy_ret),你可以在yield_value中记录参数cy_ret后面使用,yield_value的返回值如果是std::suspend_always,协程挂起,如果返回std::suspend_never ,协程就继续运行。,
,co_yield cr_ret;,调用promise.retun_value(cr_ret),如果没有返回值相当于promise.retun_viod(),你可以在retun_value中记录参数cr_ret后面使用。然后调用co_await promise.final_suspend(void),如果返回值是std::suspend_always,你需要自己手动青清理coroutine handle,调用handle.destroy()。,
,这些概念在原文第一章都有,附录在此仅供您方便参考。,协程状态(coroutine state),协程状态(coroutine state)是协程启动开始时,new空间存放协程状态,协程状态记录协程函数的参数,协程的运行状态,变量。挂起时的断点。,注意,协程状态 (coroutine state)并不是就是协程函数的返回值RET。虽然我们设计的RET一般里面也有promise和coroutine handle,大家一般也是通过RET去操作协程的恢复,获取返回值。但coroutine state理论上还应该包含协程运行参数,断点等信息。而协程状态 (coroutine state)应该是协程句柄(coroutine handle)对应的一个数据,而由系统管理的。,承诺对象(promise),承诺对象的表现形式必须是result::promise_type,result为协程函数的返回值。,承诺对象是一个实现若干接口,用于辅助协程,构造协程函数返回值;提交传递co_yield,co_return的返回值。明确协程启动阶段是否立即挂起;以及协程内部发生异常时的处理方式。其接口包括:,前面我们提到在协程创建的时候,会new协程状态(coroutine state)。你可以通过可以在 promise_type 中重载 operator new 和 operator delete,使用自己的内存分配接口。(请参考再探 C++20 协程),协程句柄(coroutine handle)是一个协程的标示,用于操作协程恢复,销毁的句柄。,协程句柄的表现形式是std::coroutine_handle<promise_type>,其模板参数为承诺对象(promise)类型。句柄有几个重要函数:,协程句柄和承诺对象之间是可以相互转化的。,co_wait 关键字会调用一个等待体对象(awaiter)。这个对象内部也有3个接口。根据接口co_wait 决定进行什么操作。,void 同返回true,bool 返回true 立即挂起,返回false 不挂起。,返回某个协程句柄(coroutine handle),立即恢复对应句柄的运行。,等待体(awaiter)值得用更加详细的笔墨书写一章,我们就放一下,先了解其有2个特化类型。,前面不少接口已经用了这2个特化的类,同时也可以明白其实协程内部不少地方其实也在使用co_wait 关键字。,此章讲解了协程的启动,3个关键字的细节。您可以通过这些关键概念,融合协程状态(coroutine state),承诺对象(promise),协程句柄(coroutine handle),等待体(awaiter)。,初探 C++20 协程,再探 C++20 协程,Coroutines (C++20),协程(coroutine)简介,The Coroutine in C++ 20 协程之诺,C++ Coroutines: Understanding operator co_await
© 版权声明
文章版权归作者所有,未经允许请勿转载。