当前位置:首页 > 科技  > 软件

漫谈c++20协程

来源: 责编: 时间:2023-11-04 23:04:06 221观看
导读Part 01、 协程是什么 协程可以理解为特数的函数,即可挂起与恢复的函数,而我们的普通函数只能一直执行到底,有没有感觉比普通的函数更厉害一些?协程一般都可以被划分为两大类,一类是有栈(tickful) 协程,例如goroutine,libc

iYa28资讯网——每日最新资讯28at.com

Part 01、  协程是什么  

协程可以理解为特数的函数,即可挂起与恢复的函数,而我们的普通函数只能一直执行到底,有没有感觉比普通的函数更厉害一些?协程一般都可以被划分为两大类,一类是有栈(tickful) 协程,例如goroutine,libco等;另一类是无栈(stackless)协程,例如C++、C#等。iYa28资讯网——每日最新资讯28at.com

这里说明一点,所谓的有栈、无栈并不是说这个协程运行的时候有没有栈,而是说协程之间是否存在调用栈,C++20协程是属于后者,协程之间调用就是通过在堆上分配协程帧空间实现的。iYa28资讯网——每日最新资讯28at.com

Part 02、  C++20协程 

C++ 20标准引入了协程(coroutine)从此C++进入了协程时代,不过C++20协程只是包含了编译器需要的底层功能,开发者使用相对复杂一些,进行封装后才可以进一步使用。iYa28资讯网——每日最新资讯28at.com

2.1 C++20协程整体流程

下面我们看一下C++20协程的整体执行流程:iYa28资讯网——每日最新资讯28at.com

图片iYa28资讯网——每日最新资讯28at.com

图1iYa28资讯网——每日最新资讯28at.com

针对上图1中的每个模块释义如下:iYa28资讯网——每日最新资讯28at.com

0、开始执行协程;iYa28资讯网——每日最新资讯28at.com

1、首先在堆上分配协程帧,大小包括实参大小,局部变量大小(包括寄存器),promise_type对象大小,协程状态等;iYa28资讯网——每日最新资讯28at.com

2、把协程的实参拷贝到协程帧中;iYa28资讯网——每日最新资讯28at.com

3、构造promise_type对象,promise_type构造函数如果与协程的构造函数完全一致,那么调用这个构造函数,否则调用默认构造函数;iYa28资讯网——每日最新资讯28at.com

4、通过promise_type对象来构造协程的返回类型Corouting_obj对象;iYa28资讯网——每日最新资讯28at.com

5、执行表达式co_awaitpromise_type.inintial_suspend(),可以挂起,此处为定制点,可以自定义协程行为;iYa28资讯网——每日最新资讯28at.com

6、如果协程在initial_suspend处挂起了,则需要等待回复进行执行;iYa28资讯网——每日最新资讯28at.com

7、协程函数体代码执行;iYa28资讯网——每日最新资讯28at.com

8、通过co_return语句返回时,将转换成对promise_type类型的return_void或return_value接口进行调用,二者选其中之一。具体看co_return后面跟着的表达式,如果没有表达式或者是void,转换为return_void,否则转换为return_value。co_return语句表示这个协程即将结束其生命期;iYa28资讯网——每日最新资讯28at.com

9、协程体内发生了异常,由unhandled_exception接口对异常进行处理;iYa28资讯网——每日最新资讯28at.com

10、final_suspend允许协程结束前挂起,当协程体内抛出异常或者通过co_return返回时都将到达这个挂起点,可以自定义行为,但不能抛出异常,所以实现时需要被修饰为noexcept;iYa28资讯网——每日最新资讯28at.com

11、堆内存申请失败,处理异常函数iYa28资讯网——每日最新资讯28at.com

promise_type::get_return_object_on_allocation_failure();

2.2 C++20协程特点

2.1节介绍了C++协程的整个执行过程,那么c++20为开发者实现协程又提供了哪些新的关键词、 以及什么样的函数看作是协程而不是普通函数呢?下面我们简单介绍一下C++20协程一些特点:iYa28资讯网——每日最新资讯28at.com

1、如果函数中包含了co_return, co_await, co_yield中的任意一个,这个函数就会被当作协程来处理;iYa28资讯网——每日最新资讯28at.com

2、协程被挂起后那么其局部变量或状态等需要被保存下来,通过操作协程句柄(corouting_handle)来管理写协程。协程句柄是一个对象,包含了分配在堆上协程帧指针和一些操作协程成员函数;iYa28资讯网——每日最新资讯28at.com

3、协程中promise_type类型能够让我们定制的有initial_suspend、final_suspend、yield_value、return_value或return_void、unhandled_exception等行为,这些行为在协程被调用时生效;iYa28资讯网——每日最新资讯28at.com

4、co_await表达式涉及了awaitable对象、awaiter对象相关概念,可以通过定义await_transform函数得到awaitable对象,可以通过重载operator co_await操作符得到awaiter对象;iYa28资讯网——每日最新资讯28at.com

2.3 C++20协程使用示例代码

下面我们通过协程实现一个简单的生成器(Generator),具体代码示例如下,代码亲测可跑,只要支持C++20特性的C++编译器即可:iYa28资讯网——每日最新资讯28at.com

#include <iostream>#include <coroutine>template<typename T>struct Generator{public:    struct ValueAwaiter{        constexpr bool await_ready(){            return false;        }        template<typename promise_type>        void await_suspend(std::coroutine_handle<promise_type> h){            h.promise().value_ = value_;        }        void await_resume(){}        T value_;    };    struct promise_type{        std::suspend_always initial_suspend() noexcept{            return {};        }        std::suspend_always final_suspend() noexcept{            return {};        }        Generator get_return_object(){            return Generator{std::coroutine_handle<promise_type>::from_promise(*this)};        }        void unhandled_exception(){            throw std::current_exception();        }        void return_void(){        }        auto await_transform(T v){            return ValueAwaiter{v};        }        std::suspend_always yield_value(T v){            value_ =v;            return {};        }    public:        T value_;    };    T next(){        handle_.resume();        return handle_.promise().value_;    }public:    std::coroutine_handle<promise_type> handle_;};Generator<int> get_number(){    int i{0};    while (true){        co_yield i++;    }}int main(){    auto g = get_number();    for(int j = 0; j < 10; ++j){        std::cout << g.next() << std::endl;    }}

上面代码中Gernerator就是一个协程object,函数get_number满足C++20协程特性使用了co_yield,因此是一个协程,而不是普通函数。执行结果如下:iYa28资讯网——每日最新资讯28at.com

图片iYa28资讯网——每日最新资讯28at.com

Part 03、 总结 

C++20只是提供了简单的协程特性,开发人员如果要用到生产环境,就需要自己开发相关库,相对难度较大一些,在未来我们可以期待有更多更好的协程库 进入后续的C++标准(C++23, C++26), 这样开发人员更好的使用协程了。iYa28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-16913-0.html漫谈c++20协程

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: SpringBoot 中实现重复提交验证功能说明及示例程序

下一篇: Jmeter分布式测试的注意事项和常见问题

标签:
  • 热门焦点
  • 石头自清洁扫拖机器人G10S评测:多年黑科技集大成之作 懒人终极福音

    石头自清洁扫拖机器人G10S评测:多年黑科技集大成之作 懒人终极福音

    科技圈经常能看到一个词叫“缝合怪”,用来形容那些把好多功能或者外观结合在一起的产品,通常这样的词是贬义词,但如果真的是产品缝合的好、缝合的实用的话,那它就成了中性词,今
  • 十个可以手动编写的 JavaScript 数组 API

    十个可以手动编写的 JavaScript 数组 API

    JavaScript 中有很多API,使用得当,会很方便,省力不少。 你知道它的原理吗? 今天这篇文章,我们将对它们进行一次小总结。现在开始吧。1.forEach()forEach()用于遍历数组接收一参
  • K8S | Service服务发现

    K8S | Service服务发现

    一、背景在微服务架构中,这里以开发环境「Dev」为基础来描述,在K8S集群中通常会开放:路由网关、注册中心、配置中心等相关服务,可以被集群外部访问;图片对于测试「Tes」环境或者
  • 得物宠物生意「狂飙」,发力“它经济”

    得物宠物生意「狂飙」,发力“它经济”

    作者|花花小萌主近日,得物宣布正式上线宠物鉴别,通过得物App内的&ldquo;在线鉴别&rdquo;,可找到鉴别宠物的选项。通过上传自家宠物的部位细节,就能收获拥有专业资质认证的得物鉴
  • “又被陈思诚骗了”

    “又被陈思诚骗了”

    作者|张思齐 出品|众面(ID:ZhongMian_ZM)如今的国产悬疑电影,成了陈思诚的天下。最近大爆电影《消失的她》票房突破30亿断层夺魁暑期档,陈思诚再度风头无两。你可以说陈思诚的
  • 阿里大调整

    阿里大调整

    来源:产品刘有媒体报道称,近期淘宝天猫集团启动了近年来最大的人力制度改革,涉及员工绩效、层级体系等多个核心事项,目前已形成一个初步的&ldquo;征求意见版&rdquo;:1、取消P序列
  • 2299元起!iQOO Pad明晚首销:性能最强天玑平板

    2299元起!iQOO Pad明晚首销:性能最强天玑平板

    5月23日,iQOO如期举行了新品发布会,除了首发安卓最强旗舰处理器的iQOO Neo8系列新机外,还在发布会上推出了旗下首款平板电脑——iQOO Pad,其最大的卖点
  • 引领旗舰级影像能力向中端机普及 OPPO K11 系列发布 1799 元起

    引领旗舰级影像能力向中端机普及 OPPO K11 系列发布 1799 元起

    7月25日,OPPO正式发布K系列新品—— OPPO K11 。此次 K11 在中端手机市场长期被忽视的影像板块发力,突破性地搭载索尼 IMX890 旗舰大底主摄,支持 OIS
  • 利用职权私自解除被封帐号 Meta开除20多名员工

    利用职权私自解除被封帐号 Meta开除20多名员工

    11月18日消息,据外媒援引知情人士表示,过去一年时间内,Facebook母公司Meta解雇或处罚了20多名员工以及合同工,指控这些人通过内部系统以不当方式重置用户帐号,其
Top