C++ 20 协程(二)
设计目标
- 高度可伸缩性
- 高效的恢复和挂起函数操作
- 与已有设施无缝衔接,没有开销
- 允许开发者设计协程库,开放高级语义的接口
- 在禁用异常的环境可以使用
成为协程
一个函数成为一个协程,通过使用以下关键字中的一个
co_return
co_await
co_yield
- 循环中的
co_await
区分协程工厂和协程对象
术语协程通常用于协程的两个方面:一个是调用了co_await
,co_yield
,co_return
的函数,另一个是协程对象
使用一个协程术语形容协程的两个方面会让人糊涂
MyFuture<int> createFuture() {
co_return 2021; }
int main() {
auto fut = createFuture();
std::cout << "fut.get(): " << fut.get() << '\n'; }
函数createFuture
是一个协程工厂返回一个协程对象。协程对象时一个可恢复对象,使用协程框架来指定他的行为
实现协程的框架包含了20多个函数,一些必须实现,一些必须重写,因此你可以定制协程的功能
一个协程与三个部分相关:
promise object
coroutine handle
coroutine frame
通过coroutine handle
协程句柄与promise object
进行交互,并将上下文保存在coroutine frame
编译器在协程执行过程中会自动调用这些函数
协程句柄(coroutine handle
)
协程句柄是一个非拥有的句柄,用于从外部恢复或销毁协程帧(frame)。协程句柄是可恢复函数的一部分。
template <typename T>
struct Generator
{
struct promise_type;
using handle_type = std::coroutine_handle<promise_type>;
Generator(handle_type h): coro(h)
{
}
handle_type coro;
~Generator()
{
if (coro) coro.destroy();
}
T getValue()
{
return coro.promise().current_value;
}
bool next()
{
coro.resume();
return not coro.done();
}
}
- 恢复协程执行:
coro.resume()
- 销毁协程:
coro.destroy()
- 检查状态:
coro
(15行)
协程帧Coroutine Frame
协程帧维持着协程堆内存的分配状态,包含promise_type
,协程复制的参数,挂起点的表示,局部变量等
- 协程的生命周期必须嵌套在调用者的生命周期内
- 协程的调用者知到协程帧的大小
协程帧的关键是可等待体(**Awaitables **),等待器(Awaiters)