C++挂起恢复协
原文
协程化异步网络库是大势所趋.
c++20协程是无栈协程,提供了:
1,三个(协待(co_await),co_yield和co_return)新关键字
2,几个新类型:coroutine_handle,coroutine_traits<T...>,suspend_always,suspend_never
3,和协程通信机制(通过协程函数的返回对象通信)
编译器根据c++协程关键字(协待,co_yield和co_return)生成协程模板框架.
需要定制框架中的各个可定制点,来实现协程的绝大部分行为.
由initial_suspend和final_suspend的返回类型来决定是否挂起协程.
在unhandled_exception里处理异常,在return_value里保存协程返回值.
存在协待,co_yield和co_return三个关键字之一,就是协程.
Task<int> sum(int a, int b) {
co_return 42;
}
生成:
{
协待 承诺.初始挂起();//挂起
试
{
承诺.返回值(42);至 止挂起;
}//保存协程返回值
抓(...)
{
承诺.未处理异常();//处理异常
}
止挂起:
协待 承诺.止挂起();//止挂起.
}
由initial_suspend和final_suspend的返回类型来决定是否挂起.定制这些函数来灵活控制协程.
协待生成:
{
动&&值=<式>;
动&&可等待=取可等待(承诺,静转<推导(值)>(值));
动&&等待器=取等待器(静转<推导(可等待)>(可等待));
//保存状态,准备恢复.
如(!等待器.准备好协())//未准备好
{
用 句柄型=实验::协程句柄<P>;
用 等待挂起果型=推导(等待器.挂起协(句柄型::从承诺(p)));//挂起协,
<挂起协程>
如 常式(是空值<等待挂起果型>)
{//挂起协//第1个断点
等待器.挂起协(句柄型::从承诺(p));
<返回到调用者或恢复者>
}//在挂起协时,暂停协程的第1个断点.
异
{
静断(是相同值<等待挂起果型,极>,
"挂起协()必须中'空'或'极'.");
如(等待器.挂起协(句柄型::从承诺(p)))
{//挂起协
<返回到调用者或恢复者>
}
}
//协程暂停后,就可`恢复或销毁`
//断点处`转移回调用者或恢复者`,从`本地堆栈帧`弹出,但保持`协程帧`活跃.
<恢复点>
}//断点处恢复协程,
中 等待器.恢复协();//恢复了,取操作结果.
}
元<类 P,类 T>
推导(动)取可等待(P&承诺,T&&式)
{
如 常式(有任何等待转换成员值<P>)
中 承诺.等待转换(静转<T&&>(式));
异
中 静转<T&&>(式);
}
元<类 W>
推导(动)取等待器(W&&w)
{//W为可等待
如 常式(有成员操作符协待值<W>)
中 静转<W&&>(w).符号 协待();
异 如 常式(无成员操作符协待值<W&&>)
中 符号 协待(静转<W&&>(w));
异
中 静转<W&&>(W);
}
在协待的模板框架里,可定制await_ready,挂起协和恢复协等.
从挂起协()的调用返回时,挂起协()的返回值为void的版本,无条件地将执行转移回协程的调用者/恢复者,而返回值为bool的版本允许awaiter对象有条件地返回并立即恢复协程,而不是返回调用者/恢复者.
挂起协()的bool返回版本在awaiter可能启动异步操作(也可同步)时非常有用.在同步时,挂起协()方法,可返回假来指示应立即恢复协程并继续执行.
在开头,保存协程的当前状态并准备恢复.
完成操作后,挂起协()负责未来调度并恢复(或消灭)协程.注意,从挂起协()中返回假算调度协程,以便在当前线程上立即恢复.
await_ready,已完成操作时,不必花费成本.
恢复协()方法调用的返回值,成为协待表达式的结果.恢复协()方法也可抛异常,此时,异常从协待表达式中抛出.
注意,如果从挂起协()抛异常,则协程会自动恢复,并且异常会从协待表达式抛出而不调用恢复协().
浙公网安备 33010602011771号