C++ 20 协程(二)

设计目标

  • 高度可伸缩性
  • 高效的恢复和挂起函数操作
  • 与已有设施无缝衔接,没有开销
  • 允许开发者设计协程库,开放高级语义的接口
  • 在禁用异常的环境可以使用

成为协程

一个函数成为一个协程,通过使用以下关键字中的一个

  • co_return
  • co_await
  • co_yield
  • 循环中的co_await

区分协程工厂和协程对象

术语协程通常用于协程的两个方面:一个是调用了co_awaitco_yieldco_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

C++ 20 协程(二)_c++20

编译器在协程执行过程中会自动调用这些函数

协程句柄(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