等待体的接口说明:
bool await_ready()
表达了等待体对象是否准备就绪,返回false表示没有准备好,返回true表示准备好了,这个返回值决定了等待体的执行流程。
bool await_suspend(Coro::coroutine_handle<Task::promise_type>)
当await_ready返回fasle时,进入此函数执行,如果await_ready返回true,则不执行此函数。
此函数的返回值可以是void,当返回值是void时,与返回值true一样。
当返回值是true时,表示协程在此挂起,挂起以后,执行权返回到调用方。
可以使用异步操作通过传递他的参数,使用resume函数恢复协程,也可以在调用方,使用协程函数的返回对象来恢复。
void await_resume()
该函数表达了co_await的返回值,返回void表示co_await没有返回值。
当await_ready返回true时,直接进入此函数。
当await_suspend恢复时,直接执行此函数。
当await_susoend没有挂起时,直接执行此函数。
该函数运行完成,则co_await表达式执行完成。
promise_type接口说明:
new 通过调用new运算符,创建协程对象的内存。
peomise_type() 调用默认构造函数初始化对象。
T get_return_object()
构造T的对象,如果对象不需要控制句柄,则可以直接返回T{ },否则 :return Coro::coroutine_handle<promise_type>::from_promise(*this);
T是包含promise_type类型的协程类。
auto initial_suspend()
初始化协程的最后一步,该函数执行完,表示协程已经准备好,下一步可以执行协程体了。
返回值是一个等待体,表达了,是否需要挂起。
如果挂起,则执行权回到调用方,等待调用方恢复,没有挂起,则开始执行协程函数。
包含此步骤之前的步骤,如果抛出异常,那么异常都将会传递给调用方。
auto await_transfoem(T expr)
该函数表示co_awiat可以接受一个expr值,并将其处理,返回一个可等待的对象(必须)。
不写此函数,编译器默认生成一个通用的版本。
编写此函数,编译器则不会生成通用版本,需要手动编写通用版本。
await_transform无法专用化,也就是特化,很特殊,编译器不允许特化。可以重载,但是重载,要尽量先编写通用的泛型版本,否则co_await表达式直接使用重载的版本。
通用的版本如下:
template<typename T> auto await_transform(T&& v) { return std::forward<T&&>(v); }
对于重载的示例可以是:
Coro::suspend_always await_transform(int&& v) { return {}; }
重载版本、所有版本,必须都在一个类中,父类的通用版本,在子类里不生效,依然会导致重载co_await决策失败,
auto yield_value(T expr)
对于co_yield表达式对应的生成器函数,expr表示co_yield 的expr,返回值是一个等待体,可以挂起,也可以不挂起。
void return_void()
协程函数没有co_return,或者co_return 没有值时,使用此函数。
void return_value(T expr)
当co_return 有值时,将值传递给expr,执行此函数。
auto final_susend() noexcept
表示协程即将结束了,此函数返回一个等待体,表示是否挂起,挂起是为了要获取协程内部的数据,挂起不能使用resume恢复,因为是最终挂起点,只能destory。
注意因为无法恢复,所以等待体的await_resume可能不会执行。
void unhandled_exception()
如果在执行协程体过程中,出现异常,协程捕获异常,并在catch块中调用此函数。
如果协程没有捕获异常结束,那么捕捉异常,调用此函数,调用final-suspend,此时恢复协程是未定义的。
如果异常是co_return触发的,那么调用承诺对象的析构函数,调用各个形参副本的析构函数,调用delete释放协程状态所有内存。
delete 运算符 释放协程状态内存。
其他:
co_await的重载,只能是类、结构体、联合体,不能是枚举、基本类型。(vs2022可以重载枚举类型)
标签:调用,co,函数,协程,await,C++,return,20 From: https://www.cnblogs.com/Super-biscuits/p/18238936