C++ Coroutine简明教程
在C++里,一个函数如果其函数体实现中包含co_await、co_yield、co_return中任何一个关键字,那么这个函数就是一个coroutine。其中:
- co_await:挂起当前的coroutine
- co_return:从当前coroutine返回一个结果
- co_yield:返回一个结果并且挂起当前的coroutine
一个coroutine要能被编译期识别并通过编译,在某些情况下要自己去特化coroutine_traits。下面就一个简单的coroutine来说一说C++编译器是如何修改这个coroutine的。
// 我们假定这个模板函数是一个coroutine
template <typename TRet, typename … TArgs>
TRet func(TArgs args…)
{
body; // body里至少包含了co_await、co_yield、co_return三者之一。
}
那么这个函数会被编译器改成如下形式:
// 它会被编译期展开成如下形式
template <typename TRet, typename ... TArgs>
TRet func(TArgs args...)
{
using promise_t = typename coroutine_traits<TRet, TArgs...>::promise_type; promise_t promise;
auto __return__ = promise.get_return_object(); // 这个__return__会被编译器特殊处理 co_await promise.initial_suspend(); try
{ // co_return expr; => promise.return_value(expr); goto final_suspend;
body; // co_return; => promise.return_void(); goto final_suspend;
} // co_yield expr; => co_await promise.yield_value(expr);
catch (...)
{
promise.set_exception(std::current_exception());
} final_suspend:
co_await promise.final_suspend();
}
以上是一个coroutine的基本形式。事实上看完之后会发现,一个coroutine的关键主要还是和其关联的promise。
和coroutine promise关联的另外一个概念,叫awaitable。Awaitable可以称为一个可等待对象。一个awaitable对象需要实现3个相关函数:
- await_ready:awaitable实例是否已经ready
- await_suspend:挂起awaitable。该函数会传入一个coroutine_handle类型的参数。这是一个由编译器生成的变量。suspend过程可以指定该coroutine何时何地以何种方式被resume。比方说实现suspend函数时,将coroutine_handle放到threadpool中。那么当前的coroutine接下来就运行在线程池指派的后台线程中运行了。
- await_resume:当coroutine重新运行时,会调用该函数。
所以要让一个类型能够awaitable,有三种手段:
- 该类型相关代码无法修改时,需要实现:
- bool await_ready(T &);
- void await_suspend(T &, coroutine_handle<promise_type>);
- auto await_resume(T &); auto视具体情况而定
- 该类型相关代码可以修改时,需要增加3个成员函数:
- bool await_ready();
- void await_suspend(coroutine_handle<promise_type> ch);
- auto await_resume();
- 实现operator co_await操作符,返回一个可等待的代理类型,并且实现了上述三个函数。
--完
C++ Coroutine简明教程的更多相关文章
- Gevent简明教程
Gevent简明教程 发表于 2015-11-28 | 分类于 技术| | 阅读次数 5159 前述 进程 线程 协程 异步 并发编程(不是并行)目前有四种方式:多进程.多线程.协程和异步. 多 ...
- 2013 duilib入门简明教程 -- 第一个程序 Hello World(3)
小伙伴们有点迫不及待了么,来看一看Hello World吧: 新建一个空的win32项目,新建一个main.cpp文件,将以下代码复制进去: #include <windows.h> #i ...
- 2013 duilib入门简明教程 -- 部分bug (11)
一.WindowImplBase的bug 在第8个教程[2013 duilib入门简明教程 -- 完整的自绘标题栏(8)]中,可以发现窗口最大化之后有两个问题, 1.最大化按钮的样式 ...
- 2013 duilib入门简明教程 -- 部分bug 2 (14)
上一个教程中提到了ActiveX的Bug,即如果主窗口直接用变量生成,则关闭窗口时会产生崩溃 如果用new的方式生成,则不会崩溃,所以给出一个临时的快速解决方案,即主窗口 ...
- 2013 duilib入门简明教程 -- 自绘控件 (15)
在[2013 duilib入门简明教程 -- 复杂控件介绍 (13)]中虽然介绍了界面设计器上的所有控件,但是还有一些控件并没有被放到界面设计器上,还有一些常用控件duilib并没有提供(比如 ...
- 2013 duilib入门简明教程 -- 事件处理和消息响应 (17)
界面的显示方面就都讲完啦,下面来介绍下控件的响应. 前面的教程只讲了按钮和Tab的响应,即在Notify函数里处理.其实duilib还提供了另外一种响应的方法,即消息映射DUI_BEG ...
- 2013 duilib入门简明教程 -- FAQ (19)
虽然前面的教程几乎把所有的知识点都罗列了,但是有很多问题经常在群里出现,所以这里再次整理一下. 需要注意的是,在下面的问题中,除了加上XML属性外,主窗口必须继承自WindowImpl ...
- Mac安装Windows 10的简明教程
每次在Mac上安装Windows都是一件非常痛苦的事情,曾经为了装Win8把整台Mac的硬盘数据都弄丢了,最后通过龟速系统恢复模式恢复了MacOSX(50M电信光纤下载了3天才把系统下载完),相信和我 ...
- Docker简明教程
Docker简明教程 [编者的话]使用Docker来写代码更高效并能有效提升自己的技能.Docker能打包你的开发环境,消除包的依赖冲突,并通过集装箱式的应用来减少开发时间和学习时间. Docker作 ...
随机推荐
- 修改vim的颜色主题 及显示行号
1.打开vim窗口,输入命令:color 或者colorscheme后回车查看当前颜色主题. 2. 输入:colorscheme <主题> 即可设置当前vim的颜色主题. sample: ...
- Redis5.0+哨兵模式+Keepalived实现高可用
Redis主备配置 原理: 从服务器向主服务器发出SYNC指令,当主服务器接到此命令后,就会调用BGSAVE指令来创建一个子进程专门进行数据持久化工作,也就是将主服务器的数据写入RDB文件中.在数据持 ...
- 小程序之 微信小程序下拉上方出现空白
往下拉页面后上方出现空白区域 用户需要手动划上去才能消失 方法一:"enablePullDownRefresh":false //这个在page.json中配置 整个页面都不能滑 ...
- 浮点型/小数/栅格图层转为整数型arcgis操作
有时候会遇到将32位栅格数据提取属性表的操作,但是一般此类数据都是浮点型,是无法计算得到属性表的.因此我们可以利用数据管理工具下的: 复制栅格工具,在最下面选择16位即可,看自己数据情况选择signe ...
- java.nio.file.NoSuchFileException
springboot +es es 2.1.0 参考这个 https://www.cnblogs.com/yueshutong/p/9381543.html cluster-nodes :改成127. ...
- Active Record Query Interface 数据查询接口(界面) 看到第8节。
http://guides.rubyonrails.org/active_record_querying.html ✅How to find records using a variety of me ...
- D - Dice Game (BFS)
A dice is a small cube, with each side having a different number of spots on it, ranging from 1 to 6 ...
- 『高性能模型』轻量级网络ShuffleNet_v1及v2
项目实现:GitHub 参考博客:CNN模型之ShuffleNet v1论文:ShuffleNet: An Extremely Efficient Convolutional Neural Netwo ...
- python 字典 dict 该注意的一些操作
在用python处理dict 的时候,有几个该注意的地方,这里跟大家提一下: 1)操作dict 时,尽量少产生新的列表对象.比如: 遍历dict的时候,如果用 dic = {"a" ...
- VUE初体验篇-安装
现代前端框架大行其道,讲前端思想从操作dom的阶段,升级到操作数据的阶段.vue作为三大前端框架之一,其中平缓的学习曲线,让好多前端新手非常喜欢,应用也越来越广泛.虽然其他两个框架有facebook, ...