首页 > 编程语言 >C++20 Corountine

C++20 Corountine

时间:2023-04-15 23:12:15浏览次数:52  
标签:调用 co Coroutine await 编译器 C++ 20 Corountine 协程

背景

C++ 20 内引入了 co_yield, co_await, co_return 三个关键字。任何函数在使用了这三个关键字中的任何一个后,都会被编译器视作协程函数,进行一些特殊编译处理。

协程介绍

协程其实就是用户态的线程(粗略的定义),协程的切换完全是在用户态进行,不需要陷入到内核态,因此切换的开销远小于线程。

协程分为有栈协程和无栈协程。

有栈协程顾名思义,每个协程都会分配栈,这会对协程的并发数量造成限制。例如Golang中每个协程默认栈大小为2KB(可能会发生扩栈)。好处是有栈协程就类似于普通的函数调用,且代码没有侵入性,可以轻松兼容现有的代码(因为有独立的栈)

无栈协程高度依赖于编译器的处理,不需要单独的为每个协程保存栈,且切换成本更低。(因为不用切换栈)

C++ 20 Coroutine

对于C++20, 语言只提供了最基础的语法支持,更多协程的标准库支持需要到C++23才能就绪。

对于协程来说,有两个概念,即挂起与恢复。

挂起:一个协程挂起后,将保存现场,暂停当前的执行。

恢复:一个协程在挂起后,可以被恢复执行。

每个协程,拥有以下几个对象:

  • Promise 对象 在堆上储存。
  • Coroutine Handle 协程句柄,借此对协程进行操作。
  • Coroutine State 协程的状态,包括协程启动时提供的参数(按值复制),该状态为动态分配,编译器生成的代码会对其进行管理。

调用过程

我们先对该协程函数进行粗糙的定义:

Coroutine F (t1 a1, t2 a2);

class Coroutine { 
    public :
     struct promise_type {
                Coroutine get_return_object();
            };
}
int main() {
    auto ret = coawait F(1, 2);
}

  

 

下面我们将介绍该协程函数的启动过程。(讨论的是编译器生成的代码)

当一个协程函数被调用后,首先会使用 operator Promise::new 构造coroutine state。(若不存在,则使用new)

在此之后,将会拷贝参数(a1, a2)到 Coroutine State 中进行保存。

其次,会调用Promise的构造函数,对其进行构造。(Promise的位置由编译器决定,具体的细节我没有找到资料,不过猜测是控制在了coroutine handler的一个固定的相对位置上)

然后会调用 promise.get_return_object() 获取返回的Coroutine对象。(该对象会作为函数的返回值

在此之后,会调用 coawait promise.initial_suspend() (coawait后面介绍)     这是一个粗略的启动过程。下面将介绍coawait   co_await 该关键字作用于一个Awaitable对象上。在上面的例子里,作用在了F的返回值上,也就是类型Coroutine上。 co_await 用于将函数的执行权交给一个协程,并在该协程挂起后,恢复执行co_await下面的代码。 Awaitable 作为co_await作用的对象,一个awaitable对象需要实现以下几个函数:
  • await_ready await
  • await_suspend(coroutine_handle<>)
  • await_resume

在我们调用 co_await <expr>时,实质上等价于编译器执行以下过程:

当通过<expr>拿到awaitable对象后(详细参考cppreference),首先会调用awaitable::await_ready(),如果返回的是true,那就直接跳过以下的所有流程,不需要挂起(可以避免性能开销,例如结果已经知道了,或者可以同步计算时)

如果返回的是false, 那么就需要进入挂起的流程。此时,当前协程的变量状态、暂停点等信息将会保存到coroutine state中。然后,awaiter::await_suspend(handle)将会被调用(这里的handle代表着当前协程的handle)。

若await_suspend返回的是void,那么控制权将立即返回给调用方。

若返回的是bool,当返回为true时,同上。返回为false时,将恢复当前协程。

最终awaiter::await_resume()将被调用。其返回值将作为整个co_await <expr>的返回值。

 

标签:调用,co,Coroutine,await,编译器,C++,20,Corountine,协程
From: https://www.cnblogs.com/dorbmon/p/17321964.html

相关文章

  • 恶意代码分析实战 lab 20-1 20-2 20-3 C++恶意代码分析
    本次实验我们将会分析lab20-1,lab20-2文件。先来看看要求解答的问题Lab20-1需要回答的问题如下Q1.在0x401040处的函数采用了什么参数?Q2.哪个URL被用来调用URLDownloadToFile?Q3.这个程序做了什么事情?Lab20-2需要回答的问题如下:Q1.在这个程序中,你可以从有趣的字符串中了......
  • 2023【xm格式转不了mp3】教你正确下载喜马拉雅mp3,并优雅获取音频!
    喜马拉雅Windows和Mac客户端下载缓存的音频是xm格式,而且限制只可使用该喜马拉雅软件才能打开,而且经过加密的,因此对于电脑小白来说就不要想着解密xm格式的文件了,而且网上基本没有xm转mp3/m4a的工具。 这次分享的不是如何将xm格式转换成mp3的工具,而是采用了跳过xm格式。直接下载......
  • NOC 2022 初中组选择和编程题题解
    NOC2022初中组选择题和编程题题解注意:本文有几个问题:部分题目我也不确定答案,而且我水平不行,有些题目我还真不会,大家就把我的答案当个参考吧。目前有一大半的题目因为作者比较懒,暂时没写,空在那儿,可以下载原题自己做做。1初中组选拔赛原题链接,提取码:efy6。1.1选择题......
  • 2023关注老年人肺功能高峰论坛在北京国家会议中心召开
    2023年4月15日,《关注老年人肺功能高峰论坛暨中药补肺丸适用性学术研讨会》在北京·国家会议中心召开。(论坛现场)本次论坛得到了医药相关部门领导、“两院”院士、联合国人类卫生健康共同体委员会、首都各大医疗机构、科研院校等众多中医药领域资深专家学者的支持,关注老年人肺功......
  • [NISACTF 2022]babyserialize
    [NISACTF2022]babyserialize<?phpinclude"waf.php";classNISA{public$fun="show_me_flag";public$txw4ever;publicfunction__wakeup(){if($this->fun=="show_me_flag"){hint();......
  • 2023.4.15
    1#include<iostream>2#include<math.h>3#definetaxbase35004usingnamespacestd;5/*typedefstruct{6intid;7charname[20];8intage;9charaddress[50];10}user;*/11typedefstruct{12longstart;13longend;14double......
  • 2023 联合省选游记 & 退役记
    退役记请翻到页面底端的后记篇。Day-1不知道为什么这次提前两天就可以颓了,于是:(Loopy20*20Hard)和同学一起解了有差不多两小时。晚上看了场电影,打了会块。Day0不知道为什么这次不能颓了。早上和下午都在对着QOJ的模板题单刷板子。多项式系列模板卡常差评感觉这......
  • C/C++运动场馆预订管理系统[2023-04-15]
    C/C++运动场馆预订管理系统[2023-04-15]题目14:运动场馆预订管理系统对旅游管理进行简单模拟。运动场地管理:包括场地名称(如羽毛球场A、乒乓球场B等)、开放时间、计费时长、价格。注意:场地可能增减、同一场地的租金在不同时间段可能不同。用户信息管理:包括用户姓名、联系方式等信......
  • solidworks 2016安装教程(win7,win10,win11都可以安装)
    以下是搜索的笔记,记录下来,方便自己下次找到一,安装关闭电脑的防护软件,禁用计算机的网络连接(禁用网卡或者拔掉网线)打开安装包,打开“_SolidSQUAD_”目录解压“_SolidSQUAD_.7z”,运行其中的“SolidWorksSerialNumbers2016.reg”写入注册表信息运行“Setup.exe”开始安装选择“......
  • 2023年4月14日
    FileProvider随着Android版本越来越高,Android官方对用户数据保护力度也越来越大。Android提供FileProvider类来供应用之间共享数据。如:<pathsxmlns:android="http://schemas.android.com/apk/res/android"><files-pathname="my_images"path="images/"/>...<......