所谓“协程”,简单点说就是一个函数可以中止运行,待“条件成熟”后,再次在断点的地方重新运行,即能以“进入-暂停-继续-暂停…”这样的方式运行函数,因此讨论协程,需要关心下面几个问题:
- 在运行点暂停,然后再运行—暂停点的记录
- 暂停时的运行环境,恢复运行时,应首先恢复当时的环境—运行环境的记录
- 因协程状态是变化的,因此需要有办法查询协程当前的运行状态,包括返回值、异常等—协程状态的记录
异步操作是 “慢”资源与“快”资源协调编程方面的一个“老”问题,协程的目标就是试图以“同步的形式”编写出异步操作的效果。
以前,C++协程的实现可以通过第三方库来实现的,例如Boost就有两种协程实现(Boost.coroutine2中的协程和Boost.Asio中的协程,见笔者的博文),现在,协程从语言标准层面得以支持,也就是不需要第三方库了。
C++20增加了库<coroutine>,需要协程支持时应包含该文件(【注】gcc10.2编译时需要添加-fcoroutines)。
C++的协程是无栈(stackless)协程,与一个协程关联的有三个对象:
一个promise_type内部对象,保存协程的结果(或发生的异常)
一个handle,从外部可以用来恢复执行或销毁协程
一个可保存coroutine state的内部对象,从堆中分配空间(因而是stackless),包括以下内容:
- 所有的函数参数(值参数和引用参数,这里需要注意的是引用参数,如果协程的生命期比被引用的参数长,则这些引用参数会因不可用而变得很“危险”)
- 当前中断点
- 那些跨越中断点前后的(局部)变量
为表达协程,C++引入了三个关键字:co_return,co_yield和co_await。
co_await:一元操作符。co_await用法为co_await expr,其中expr需要满足一定条件(即awaitable),它要含有以下三个函数:
bool await_ready()
void awai