协程
协程是能暂停执行以在之后恢复的函数。协程是无栈的:它们通过返回到调用方暂停执行,并且恢复执行所需的数据与栈分离存储。这样就可以编写异步执行的顺序代码(例如不使用显式的回调来处理非阻塞 I/O),还支持作用于惰性计算的无限序列上的算法及其他用途。
编译器通过co_await,co_yield,co_return三个关键字将函数识别为协程函数,只要有其中一个即可。一般协程的声明如下所示:
Generator<T>
function_name(val ...){
...
co_yield -1;
...
}
//比起协程的定义,类型Generator<T>的声明具有更多的限制。
相关概念介绍
协程关键字(可重载)
co_await:暂停协程并将控制返回给调用方。后方跟等待器,暂停效果依赖等待器。
co_yield:向调用方返回一个值并暂停当前协程。暂停效果依赖目标函数返回的等待器。
co_return:结束协程,并返回一个值,也可以不返回值。
必要依赖
suspend_always (挂起——持续):协程提供的状态控制类型,在特化的函数中作为返回值时会暂停协程。
suspend_never (挂起——不):协程提供的状态控制类型,在特化的函数中作为返回值时不会暂停协程。
Generator<T> :自定义类型,用于封装调用协程的逻辑。用户可以随自己喜好定义,但要保持一致。在本文中使用Generator表示。
handle_type (协程句柄类型):必须为 coroutine_handle<promise_type>。原则上直接使用 coroutine_handle<promise_type> 是一样的,但这样好看。
promise_type(承诺对象类型):一个类,内部定义控制协程的各种函数。被关联到协程的定义、结束、异常以及co_await,co_yield,co_return;准确来说需要在这个类中提供上述过程的实现。
promise_type::get_return_object():获取协程对象,返回值必须是Generator<T>。创建协程对象时由程序自动调用。函数的一般实现为:
Generator get_return_object() { return Generator(handle_type::from_promise(*this)); } //与函数initial_suspend先后执行,因此感觉并没有修改本函数的必要。(但却要我们自己写这段代码,稍微有点不理解)
promise_type::initial_suspend():协程的初始化函数,一般为空。返回值必须为等待器。
promise_type::final_suspend():协程的结尾函数,一般为空。返回值必须为等待器。若返回的等待器不具备暂停协程的功效,会导致协程对象失效。
promise_type::unhandled_exception():发生未处理的异常时调用。
co_await依赖
等待器 类型:suspend_always与suspend_never就是协程库提供的等待器类型。等待器需要实现下方三个函数:
bool await_ready():返回false时暂停协程,并调用函数await_suspend( 本协程句柄 )。
await_suspend(coroutine_handle<>):返回类型为void时将控制权返回调用方,返回bool类型true等于返回void,返回false时恢复此协程。而返回其他协程句柄时,则恢复该协程。
await_resume():最后执行,返回值被用作co_await表达式的值。返回类型可自行定义。
co_yield依赖
yield_value(传递值类型):返回值必须时等待器。参数为co_yield中传递的值,一般会设立一个变量保留起来。
co_return依赖
void return_void():直接结束协程时调用。
void return_value(传递值类型):结束协程时返回值时调用。类似yield_value。
//上述两个函数的返回值必须是void,之所以与co_await与co_yield不同,是因为之后会立即调用promise_type::final_suspend()。
最后
为了更加方便的使用,本文做了大量化简。如果需要进一步了解可以移步网站:协程 (C++20) - cppreference.com。
标签:suspend,return,协程,await,C++,yield,co From: https://www.cnblogs.com/dkyedaxxuh/p/16616722.html