下面来分析一下协程的流程。通过这次分析,希望梳理一下协程的几个重要概念之间的关系,把这几个点联系起来。所以在概念参考中我们列出了相应的概念文本。协程的创建在启动C++20协程之前,将创建一个新的协程状态(协程状态)。然后构造协程的promise对象(promise)。承诺对象(promise)通过get_return_object()构造协程的返回值结果。当协程第一次挂起时,这个返回值被分配给调用者。然后通过co_awaitpromise.initial_suspend(),确定初始测试完成后协程的行为。如果返回std::suspend_always,则暂停初始化,如果返回std::suspend_never,则在初始化后继续执行。(注意initial_suspend也可以返回其他协程体)协程的co_awaitcw_ret=co_awaitawaiter或cw_ret=co_awaitfun(),先计算表达式fun,fun返回结果,是一个等待体awaiter。系统首先调用awaiter.await_ready()接口查看等待体是否就绪,如果未就绪则调用awaiter.await_suspend()(返回false)。await_suspend根据参数记录调用它的协程句柄。await_suspend的返回值是returntrue,或者returnvoid会暂停协程。之后,如果外部恢复执行协程,则调用awaiter.await_resume()接口。它将结果作为co_await的返回值返回。协程的co_yieldco_yieldcy_ret;相当于调用co_waitpromise.yield_value(cy_ret),在yield_value中记录参数cy_ret后即可使用,如果yield_value的返回值为std::suspend_always,协程被挂起,如果返回std::suspend_never,协程继续运行。co_returnco_yieldcr_ret;的协程,调用promise.retun_value(cr_ret),如果没有等价于promise.retun_viod()的返回值,可以在return_value中记录参数cr_ret后使用。然后调用co_awaitpromise.final_suspend(void),如果返回值为std::suspend_always,需要手动清理协程句柄并调用handle.destroy()。这里有个问题,final_suspend,并没有真正挂起协程。查看C++参考,其中还说调用promise.final_suspend()和co_waits结果。。据说如果返回,应该暂停。但是用VS2022测试不会suspend,再去探查C++20协程文章如果返回std::suspend_always,需要自己清理协程句柄。对此感到怀疑。概念参考附录:这些概念包含在原文第一章中,这里的附录只是为了方便大家。协程状态(coroutinestate)是协程启动时,新的空间存放协程状态,协程状态记录了协程函数的参数,协程的运行状态,变量。挂断点。注意协程状态(coroutinestate)并不是协程函数的返回值RET。虽然我们设计的RET一般也有promise和协程句柄,但是大家一般都是用RET来操作协程的回收,获取返回值。但是协程状态理论上应该也包含协程运行参数、断点等信息。协程状态应该是协程句柄对应的一段数据,由系统管理。承诺对象(promise)承诺对象的表达形式必须是result::promise_type,result是协程函数的返回值。Promise对象是几个接口的实现,用来辅助协程,构造协程函数的返回值;提交并传递co_yield和co_return的返回值。指定协程启动阶段是否立即挂起;以及如何处理协程内部的异常。它的接口包括:autoget_return_object():用于生成协程函数的返回对象。autoinitial_suspend():用于明确协程函数初始化后的执行行为,返回值是awaiter,返回值是用co_wait调用的。std::suspend_always的返回值表示协程启动后立即挂起(不执行协程函数第一行代码),std::suspend_never的返回值表示协程不立即挂起开始后。(当然,既然是返回等待体,这里可以选择做什么样的等待操作)voidreturn_value(Tv):调用co_returnv后会调用该函数,可以保存co_return的结果autoyield_value(Tv):调用co_yield后会调用这个函数,可以保存co_yield的结果,其返回值为std::suspend_always,表示协程会被挂起。如果返回std::suspend_never,表示不会被挂起。autofinal_suspend()noexcept:协程退出时调用的接口,返回std::suspend_never,自动销毁协程状态对象。如果final_suspend返回std::suspend_always,用户需要调用handle.destroy()销毁它。但值得注意的是,返回std::suspend_always并不会挂起协程。前面我们提到,创建协程时,协程状态会是new的。您可以通过在promise_type中重载operatornew和operatordelete来使用自己的内存分配接口。(请参考RevisitingC++20Coroutine)协程句柄(coroutinehandle)是一个协程标记,用于操作协程回收和销毁句柄。协程句柄的表达形式为std::coroutine_handle
