协程详解
前言
最近在学协程库,因为计划是12月底之前,时间有限想着直接从代码起步,果然这样子还是不好的,这几天很多东西处于一种似懂非懂的状态,很难受。所以决定写篇文章重新捋一下,之前也写过一点点,但是太浅了。
主要参考有没有C++大佬把C++20的协程讲解下? - 知乎这个问题中南山烟雨珠江潮 - 知乎的回答,以及代码随想录的协程库源码。
正文
进程线程协程
进程,线程,协程之间的关系,出现的原因,历史渊源等
理解进程和线程从基本概念着手,
进程可以简单认为是由程序代码,相关数据还有进程控制块组成的。操作系统基本职责是控制进程的执行,这包括交替执行的方式以及为进程分配资源。
倘若我们要执行一个任务,如果全由进程从头至尾执行那必然效率一般,会思考如果将任务分成不同部分,交由不同的进程并行执行能不能提高效率?进程间的地址空间一般来说都是独立不能互相访问的,如果想要通信必须经过内核,那很明显执行一个任务多次进入内核是得不偿失的。因此出现了线程,线程是由线程id,程序计数器,寄存器集合和栈组成,一个进程可以有多个线程,线程之间是共享地址空间的,同时多核cpu能够让多线程并行执行,成功达到了提高性能的作用。所以也可以理解成,线程解决了进程的并行问题。
对于进程和线程,其实还有很多可以讨论的问题,比如进程间的通信方式;多线程需要共享数据,那么如何避免冲突;进程最多可以创建多少个线程;线程崩溃进程也会崩溃吗;死锁,悲观锁,乐观锁,共享锁,排他锁,这么多锁的说法到底是怎么一回事。这些如果讲起来就有点偏离本篇协程的主题了,因此估计会再写一篇文章吧,留个悬念。
协程的使用
https://www.cnblogs.com/blizzard8204/p/17563217.html
语言:C++20 C++20的协程是一个无栈,非对称的协程。
| |
协程学习
https://lewissbaker.github.io/2017/09/25/coroutine-theory
协程是函数的泛化。
对于函数而言,存在两个操作:call和return。
发生call时,call创建一个激活框架,暂停调用函数的执行,同时将执行转移到调用函数的开始处;return时将返回值传递给调用者,恢复原本调用者的状态,销毁激活框架。这里的激活框架可以视为保存函数特定调用的当前状态的内存块,同时这套激活框架也被成为‘堆栈’。
协程中有三个新的语言关键字:
co_await、co_yield和co_return命名空间中的几种新类型
std::experimental""coroutine_handle<P>coroutine_traits<Ts...>suspend_alwayssuspend_never
库编写者可以使用该机制与协程交互并定制其行为。
一种语言工具,使编写异步代码变得更加容易!
当前的协程并没有定义协程的语义。它没有定义如何生成返回给调用者的值。它没有定义如何处理传递给语句的返回值co_return,或者如何处理从协程传播出去的异常。它没有定义应该在哪个线程上恢复协程。相反,它指定了一种通用机制,让库代码通过实现符合特定接口的类型来定制协程的行为。
比如可以定义一个异步生成单个值的协程,或者一个延迟生成一系列值的协程,或者一个通过遇到值optional<T>时提前退出简化使用值的协程。
协程TS定义了两种接口:Promise接口和Awaitable接口
- Promise接口指定了自定义协程本身行为的方法。库编写者能够自定义调用协程时发生的情况、协程返回时发生的情况(无论是通过正常方式还是通过未处理的异常),以及自定义协程中任何
co_await或表达式的行为。co_yield - Awaitable接口指定了控制表达式语义的方法
co_await。当传入一个值时co_await,代码将被转换为对 awaitable 对象上的一系列方法的调用,这些方法允许它指定:是否暂停当前协程、在暂停后执行某些逻辑以安排协程稍后恢复、以及在协程恢复后执行某些逻辑以产生表达式的结果co_await。
接口清单:
Awaitable
- awaiter type需要实现如下名字的函数:
- await_ready
- await_suspend
- await_resume
- awaitable type需要实现如下的操作符重载:
- operator co_await()
Promise
- promise type需要实现如下名字的函数:
- get_return_object
- initial_suspend
- final_suspend
- unhandled_exception
- return_void
- promise type可选实现如下名字的函数:
- return_value
- operater new
- operater delete
- get_return_object_on_allocation_failure
- yield_value(co_yield)
- await_transform
https://yearn.xyz/posts/techs/%E5%8D%8F%E7%A8%8B/
https://itnext.io/c-20-coroutines-complete-guide-7c3fc08db89d
