co_await expr

​co_await(协待)​​是​​C++20​​新关键字.上面表示等待​​懒求值​​任务.不希望该任务阻塞​​调用者​​,用​​协待​​挂起​​任务​​.调用者继续.任务完成后,​​协待​​返回​​协程​​的结果.有两个作用:​​挂起协程及取协程返回值​​.

​协待​​等待任务时,不阻塞​​调用者​​,就是​​协程​​化​​异步​​为​​同步​​的关键.

​协待​​类似​​调用函数​​.对象有​​()​​时是​​可调用​​的.对象支持​​协待()​​时,就是​​可等待​​的.​​协待​​后的​​式​​为​​可等待​​式.

总是挂起
协待 从不挂起;
测试(){
协待 总是挂起{};
}//错误,缺少承诺类型.

​协待​​​必须在​​协程​​​中,​​协程​​​必须要有​​承诺类型​​​.通过它返回​​内外通信对象​​.

 任务{//任务
承诺类型{
任务 取中对象(){{协程句柄<任务::承诺类型>::从承诺(*)};}
从不挂起 初始挂起(){{};}
从不挂起 止挂起()无异{{};}
中空(){}
未处理异常(){}
};

协程句柄<任务::承诺类型>句柄_;
};

任务 测试(){
协待 总是挂起{};//.1
}

​.1​​​转换为前面见过的​​模板框架代码​​:

{//
&&=总是挂起{};
//先取表达式值.
&&w=取可等待(承诺,静转<推导()>());
//然后取`可等待`.
&&等待器=取等待器(静转<推导(w)>(w));
(!等待器.准备好协())
{
句柄型=实验::协程句柄<P>;
等待挂起果型=推导(等待器.挂起协(句柄型::从承诺(p)));
<挂起协程>
常式(是空值<等待挂起果型>)
{
等待器.挂起协(句柄型::从承诺(p));
<返回到调用者或恢复者>
} {
静断(是相同值<等待挂起果型,>,
"挂起协()必须中'空'或'极'.");

(等待器.挂起协(句柄型::从承诺(p)))
{
<返回到调用者或恢复者>
}
}

<恢复点>
}

等待器.恢复协();
}
//取可等待的代码
< P, T>
推导()取可等待(P&承诺,T&&)
{
常式(有任何等待转换成员值<P>)
承诺.等待转换(静转<T&&>());

静转<T&&>();
}

如果协程的​​承诺​​​中定义了​​await_transform​​​,那么就调用​​它​​​来得到​​可等待​​​,否则就按​​可等待​​​返回自己,这里,未在​​task​​​里面定义​​await_transform​​​,因此​​总是挂起​​​将为​​可等待​​,实现代码:

 总是挂起{
常式 准备好协() 无异 ;
常式 挂起协(协程句柄<>) 无异{}
常式 恢复协() 无异{}
};

取了​​总是挂起​​​后,再根据它来取​​等待器​​,代码:

< W>
推导()取等待器(W&&w)
{
常式(有成员操作符协待值<W>)
静转<W&&>(w).符号 协待();
//有自身的`协待
常式(无成员操作符协待值<W&&>)
符号 协待(静转<W&&>(w));//全局协待

静转<W&&>(w);//自身转为`等待器`.
}

​等待器​​是​​可等待​​的返回​​对象​​.1,用专门带​​约束​​对象来实现​​挂起协程​​和​​取协程返回值​​.2,​​灵活性和扩展性​​.​​可等待​​作为间接层,保存​​协待​​环境,可做更多事情.

​等待器​​必须实现​​准备好等待(.1)/挂起等待(.2)/恢复等待(.3)​​.

​.1​​为假,就挂起协程,调用​​.2​​.如果​​.2​​返回​​真/空​​,就返回到​​调用者​​.返回​​假​​,就执行​​协待​​下面语句.​​.1​​为真,说明执行完协程,调用​​.3​​返回​​协程结果​​.

展示协待

 任务{
承诺类型{
任务 取中对象(){{协程句柄<任务::承诺类型>::从承诺(*)};}
从不挂起 初始挂起(){{};}
从不挂起 止挂起()无异{{};}
中空(){ 输出<<"取协程结果\n"; }//5
未处理异常(){}
};

协程句柄<任务::承诺类型>句柄_;//外部控制.
};

任务 测试(){
输出<<"创建协程\n";//1
协待 总是挂起{};//在这里挂起了.
输出<<"这是恢复点\n";//4
}
(){
t=测试();输出<<"现在返回调用者\n";//2
输出<<"调用者恢复挂起协程\n";t.句柄_();//3
输出<<"消灭协程\n";//6
}

可定义​​等待器​​,控制它的​​.1和.2​​来控制协程.

一般在​​.2​​中发起​​异步​​操作,此时​​协程​​是挂起的.返回​​调用者​​不阻塞.完成​​异步​​操作后,通过​​.3​​返回​​协程返回值​​,并恢复协程.结束​​协待​​,调用者拿到​​结果​​.