协程:可暂停,可恢复
,对异步/惰性计算
很方便.用co_await
暂停,co_yield
暂停并返回一个值,co_return
完成并返回值.无栈协程
可利用类似达夫
设备,来搞定协程
.即内部保存有状态
.对称/非对称
协程,类似星形与三角形
之间关系.对称
都平等,非对称
,则每次都要往返
.协待
后的表达式,必须有await_ready,await_suspend,await_resume
三个函数.如总是挂起
对象.1表示是否必须异步,2暂停前准备(有最重要的coroutine_handle(用来外部控制)参数),3,恢复协程.
.承诺
,根据协程返回值
,用coroutine_traits
取返回类型.
using T = coroutine_traits<return_type, Args...>;
using promise_type = T::promise_type;
取得返回类型
.然后分配帧对象
.承诺类型
必须有几个接口:get_return_object,initial_suspend,final_suspend,unhandled_exception,return_value,return_void
函数.这是返回对象
.承诺对象
内部控制协程
,协程句柄
外部控制.他们保存在帧上,相差不远(10h~20h)
.协程句柄内部有个:
struct _Resumable_frame_prefix {
using _Resume_fn = void(__cdecl*)(void*);
_Resume_fn _Fn;//恢复地址.
uint16_t _Index;///索引点
uint16_t _Flags;
};//有个帧前缀.
protected:
_Resumable_frame_prefix* _Ptr = nullptr;
上面是coroutine_handle
的部分.协程状态包括承诺对象,参数,临时变量和协程句柄里的_Resumable_frame_prefix
std::experimental::coroutine_handle<> g_h;
struct awaitee {
bool await_ready() noexcept {return false;}
void await_suspend(std::experimental::coroutine_handle<> h) noexcept {g_h = h;}
void await_resume() noexcept {}
};
//协待,表达式,必须实现三个接口
template<typename ...Args>
return_object test_coroutine(Args... args) {
co_await awaitee();co_return 1;
}
int main() {
auto& ret = test_coroutine();
if (ret.get_ret() == 0) {
g_h.resume();
}
std::cout << "协程结束了." << ret.get_ret() << std::endl;
return 0;
}
其实就是一个帧
,里面有承诺对象+协程句柄,两个相距距离就是承诺对象大小(但要16字节对齐)
.就是保存一个恢复点地址表
,里面有个索引
,每次就修改这个索引.从2
开始,0与1留给取消操作的暂停与恢复点
.汇编嘛,都是跳跳跳
.
协程最关键就是暂停/恢复
函数执行.通过编译器记录跳转点
来实现.协程对象,只包含承诺对象、形参信息、临时变量、协程句柄
.比回调多了协程句柄(1个函数指针+2个状态值)
,执行时,只计算一个地址,然后就跳转
.所以不麻烦.
参考地址