Coroutine 学习总结

参考 tnie/learn_xxx 中 coro 项目。

如果想看懂 asio 如何支持 co_await 的,想更细致地用好协程,就需要了解更基础(同时也是更复杂的)内容。

第一章

微软专家 C++ coroutines: Getting started with awaitable objects 开篇的陈述,比我的倾向更具说服力:

Coroutines were added to C++20, and Lewis Baker has a nice introduction to them.

特别推荐这几篇文章,作者写了 cppcoro 库,牛人!

首推,此系列的文章作为入门。

对协程介绍时,先介绍 awaitable/awaiterpromise。学习笔记/摘抄,见 coroutine-a~c.md

微软的这篇博客很短,但内容很丰富。给出了一份 magic demo,很精彩。

第二章

从HelloWold开始,深入浅出C++ 20 Coroutine TS,作者分析了 IDE 生成的汇编语言,介绍了协程“如何保存状态,如何跳转”。可惜我看不懂。

对称协程只是非对称协程的一个特例,我们可以通过添加一个中立的第三方调度中心的方式将非对称协程转换成对称协程(只需要在所有协程“暂停”时将控制权转交给调度中心统一调度即可)。

猜测 asio 的 awaitable<>co_spawn 也是干了这件事

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
struct suspend_always
{
bool await_ready() _NOEXCEPT {
return false;
}
void await_suspend(coroutine_handle<>) _NOEXCEPT {}
void await_resume() _NOEXCEPT {}
};

struct suspend_never
{
bool await_ready() _NOEXCEPT {
return true;
}
void await_suspend(coroutine_handle<>) _NOEXCEPT {}
void await_resume() _NOEXCEPT {}
};

co_await 表达式展开后是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
// co_await std::experimental::suspend_always{};
{
auto&& tmp = std::experimental::suspend_always{};
if (!tmp.await_ready()) {
__builtin_coro_save() // frame->suspend_index = m;
if (tmp.await_suspend(<coroutine_handle>)) {
__builtin_coro_suspend() // jmp
}
}

resume_label_m:
tmp.await_resume();
}

其他

  • COROUTINES INTRODUCTION,需要科学上网,PAC 全局

    关键的 __builtin_coro_save()return_to_the_caller() 组合是如何实现功能的呢?作者并没有介绍,系列的三篇文章只是详细地讲解了各个代码定制点以及编译器如何展开并生成样本的代码,却对关键的“如何保存与跳转”只字未提。

    对协程介绍时,先介绍 promiseawaitable/awaiter。学习笔记/摘抄,见 coroutine1~3.md

  • C++20 协程初探

    抽空,学习一下他的例子。

  • C++20 Coroutine

    作者应该也是小白用户,几个关键点都提到了,但展开得不够,轻重也没区分。罗列概念、罗列代码

  • TAG : COROUTINE

    貌似高屋建瓴,但真的就是“乱拳打死老师傅”。有价值,但对小白入门非常不友好,得自行筛选。