C++并发之协程实例(三)(co_await)

目录

  • 1 协程
  • 2 实例
  • 3 运行

1 协程

  协程(Coroutines)是一个可以挂起执行以便稍后恢复的函数。协程是无堆栈的:它们通过返回到调用方来暂停执行,并且恢复执行所需的数据与堆栈分开存储。这允许异步执行的顺序代码(例如,在没有显式回调的情况下处理非阻塞I/O),还支持惰性计算无限序列上的算法和其他用途。
协程类图如下:
协程类

2 实例

#include <coroutine> //for std::coroutine_handle std::suspend_never
#include <iostream>
#include <utility>template <class T>
struct task
{struct promise_type{auto  get_return_object(){std::cout << "in get_return_object" << std::endl;return task(std::coroutine_handle<promise_type>::from_promise(*this));}std::suspend_always initial_suspend() {std::cout << "in initial_suspend" << std::endl;return {}; }struct final_awaiter{bool await_ready() noexcept{ std::cout << "in final_awaiter.await_ready" << std::endl;return false;}void await_resume() noexcept {std::cout << "in final_awaiter.await_resume" << std::endl;}std::coroutine_handle<>await_suspend(std::coroutine_handle<promise_type> h) noexcept{std::cout << "in final_awaiter.await_suspend" << std::endl;if(auto previous = h.promise().previous; previous){std::cout << "in final_awaiter.await_suspend.previous" << std::endl;return previous;}else{std::cout << "in final_awaiter.await_suspend.noop_coroutine" << std::endl;return std::noop_coroutine();}}};final_awaiter final_suspend() noexcept {std::cout << "in final_suspend" << std::endl;return {}; }void unhandled_exception() {std::cout << "in unhandled_exception" << std::endl;throw; }void return_value(T value) {std::cout << "in return_value" << std::endl;result = std::move(value); }T result;std::coroutine_handle<> previous;};task(std::coroutine_handle<promise_type> h) : coro(h) {}task(task &&) = delete;~task() { coro.destroy(); }struct awaiter{bool await_ready() {std::cout << "in awaiter.await_ready" << std::endl;return false; }T await_resume() {std::cout << "in awaiter.await_resume" << std::endl;return std::move(coro.promise().result);}auto await_suspend(std::coroutine_handle<> h){std::cout << "in awaiter.await_suspend" << std::endl;coro.promise().previous = h;return coro;}std::coroutine_handle<promise_type> coro;};awaiter operator co_await(){ std::cout << "in co_await" << std::endl;return awaiter{coro};}T operator()(){std::cout << "in operator()" << std::endl;coro.resume();return std::move(coro.promise().result);}private:std::coroutine_handle<promise_type> coro;
};task<int> get_random()
{std::cout << "in get_random\n";co_return 4;
}task<int> test()
{task<int> v = get_random();task<int> u = get_random();std::cout << "in test()\n";int x = (co_await v + co_await u);co_return x;
}int main()
{std::cout << "before test\n";task<int> t = test();std::cout << "after test\n";int result = t();std::cout << "after t()\n";std::cout << result << std::endl;return 0;
}

3 运行

before test
in get_return_object                             创建协程t
in initial_suspend                               挂起t
after test
in operator()                                    调用t()->{ resume, return result; }
in get_return_object                             创建携程v
in initial_suspend                               挂起v
in get_return_object                             创建携程u
in initial_suspend                               挂起u
in test()
in co_await                                      调用v.co_wait
in co_await                                      调用u.co_wait
in awaiter.await_ready                           调用v.awaiter.await_ready
in awaiter.await_suspend                         调用v.awaiter.await_suspend,保存到previous,返回原来的coro
in get_random
in return_value                                  调用v.promise_type.return_value
in final_suspend                                 调用v.promise_type.final_suspend,返回final_awaiter
in final_awaiter.await_ready                     调用v.final_awaiter.await_ready
in final_awaiter.await_suspend                   调用v.final_awaiter.await_suspend
in final_awaiter.await_suspend.previous          返回v之前的previous
in awaiter.await_ready                           调用u.awaiter.await_ready
in awaiter.await_suspend                         调用u.awaiter.await_suspend,保存到previous,返回原来的coro
in get_random
in return_value                                  调用u.promise_type.return_value
in final_suspend                                 调用u.promise_type.final_suspend,返回final_awaiter
in final_awaiter.await_ready                     调用u.final_awaiter.await_ready
in final_awaiter.await_suspend                   调用u.final_awaiter.await_suspend
in final_awaiter.await_suspend.previous          返回u之前的previous
in awaiter.await_resume                          调用v.awaiter.await_resume,返回值  
in awaiter.await_resume                          调用u.awaiter.await_resume,返回值    
in test.x
in return_value                                  调用t.promise_type.return_value
in final_suspend                                 调用t.promise_type.final_suspend,返回final_awaiter             
in final_awaiter.await_ready                     调用t.final_awaiter.await_ready
in final_awaiter.await_suspend                   调用t.final_awaiter.await_suspend
in final_awaiter.await_suspend.noop_coroutine    返回noop_coroutine,不做后续操作
after t()
8

说明:

  • 由于t挂起后立即调用resume,所以t的awaiter没有被调用,所以t.final_awaiter.await_suspend返回的是noop_coroutine

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/357389.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

指纹浏览器与虚拟机的区别及在跨境电商中的应用

在如今数字化世界中&#xff0c;隐私和安全变得愈发重要。许多人在网络上进行敏感操作&#xff0c;如网上购物、在线银行、社交媒体管理等。为了保护自己的隐私&#xff0c;人们常常会寻求一些额外的工具&#xff0c;比如指纹浏览器和虚拟机。这两种工具在保护个人隐私方面都有…

sqoop的安装配置

1. 上传并解压安装包 tar -zxvf sqoop-1.4.7.bin__hadoop-2.6.0.tar.gz -C ../server/ 重命名&#xff1a;mv sqoop-1.4.7.bin__hadoop-2.6.0 sqoop 2. 配置环境变量 sudo vim /etc/profile # 配置sqoop的环境变量 export SQOOP_HOME/export/server/sqoop export PATH$PATH…

Linux htop命令使用

文章目录 简介界面介绍第一行第二行第三行第四行 如何使用 简介 htop 是一个类似于 top 的命令&#xff0c;但具有更丰富的功能和更友好的界面。它可以实时显示系统中各个进程的资源占用情况&#xff0c;如 CPU 使用率、内存使用率等。以下是对 htop 命令的完全解析&#xff1…

嵌入式实验---实验五 串口数据接收实验

一、实验目的 1、掌握STM32F103串口数据接收程序设计流程&#xff1b; 2、熟悉STM32固件库的基本使用。 二、实验原理 1、STM32F103R6能通过查询中断方式接收数据&#xff0c;每接收到一个字节&#xff0c;立即向对方发送一个相同内容的字节&#xff0c;并把该字节的十六进…

Python: HexBinDecOct

因为&#xff1a; f0b1001110# 十进制 int()a0*2**01*2**11*2**21*2**30*2**40*2**51*2**6print(a)# 八进制 oct()print(78/8,78%8)# 110 001 001 8 116print(1*2**00*2**10*2**2,1*2**00*2**10*2**2,0*2**01*2**11*2**2)#十六进制 hex()#0 100 1110 16 4Eprint(sixteenFoo(0*…

如何在Qt Designer中管理QSplitter

问题描述 当按下按钮时&#xff0c;我希望弹出一个对话框&#xff0c;用户可以在其中选择内容并最终按下 ‘Ok’ 按钮。我想在这个对话框中放置一个 QSplitter&#xff0c;左侧面板将显示树状结构&#xff0c;右侧将显示其他内容。如何正确实现这一点&#xff1f; 从 Qt 的示…

oracle 主从库中,从库APPLIED为YES ,但是主库任然为NO

主库 从库 从库已经APPLIED但是主库为APPLIED&#xff0c; 主数据库和备用数据库之间的ARCH-RFS心跳Ping负责更新主数据库上v$archived_log的APPLICED列。 在主数据库上有一个指定的心跳ARCn进程来执行此Ping。如果此进程开始挂起&#xff0c;它将不再与远程RFS进程通信&#…

git拉取gitee项目到本地

git安装等不做赘述。 根据需要选择不同操作 1.只是单纯拉取个项目&#xff0c;没有后续的追踪等操作 不需要使用git init初始化本地文件夹 新建一个文件夹用于存储项目&#xff0c;右键选择 git bash here 会出现命令行窗口 如果像我一样&#xff0c;只是拉取个项目作业&…

Python爬虫技术:动态JavaScript加载音频的解析

在当今的互联网世界中&#xff0c;JavaScript已成为构建丰富交互体验不可或缺的技术。然而&#xff0c;对于网络爬虫开发者来说&#xff0c;JavaScript动态生成的内容却带来了不小的挑战。音频内容的动态加载尤其如此&#xff0c;因为它们往往涉及到复杂的用户交互和异步数据加…

xxe漏洞学习

一、什么是xxe漏洞 XXE就是XML外部实体注入&#xff0c;当允许引用外部实体时&#xff0c; XML数据在传输中有可能会被不法分子被修改&#xff0c;如果服务器执行被恶意插入的代码&#xff0c;就可以实现攻击的目的攻击者可以通过构造恶意内容&#xff0c;就可能导致任意文件读…

kafka(四)消息类型

一、同步消息 1、生产者 同步发送的意思就是&#xff0c;一条消息发送之后&#xff0c;会阻塞当前线程&#xff0c;直至返回 ack。 由于 send 方法返回的是一个 Future 对象&#xff0c;根据 Futrue 对象的特点&#xff0c;我们也可以实现同 步发送的效果&#xff0c;只需在调…

python---OpenCv(二),背景分离方法较有意思

目录 边界矩形 旋转矩形(最小外接矩形): 计算轮廓 找4个点的坐标 把浮点型转为Int 画轮廓 边界矩形--&#xff08;最大外接矩形&#xff09; 转灰度 找轮廓 找顶点 画矩形 显示 背景分离方法&#xff08;这个很好玩&#xff0c;可以识别在动的物体&#xff09; 边…

Redis源码学习:quicklist的设计与实现

为什么需要quicklist 假设你已经知道了ziplist的缺陷&#xff1a; 虽然节省空间&#xff0c;但是申请内存必须是连续的&#xff0c;如果内存占用比较多&#xff0c;申请效率低要存储大量数据&#xff0c;超过了ziplist的最佳上限后&#xff0c;性能有影响 借鉴分片思想&…

栅格数据重心迁移变化分析

目前网络上大多是针对矢量重心迁移进行计算&#xff0c;或把栅格转矢量在进行计算&#xff0c;可以不用怎么麻烦&#xff0c;可以直接利用栅格进行得出多期数据的重心&#xff0c;然后进行变化分析等方面的分析。 矢量数据可以通过下面方式进行重心计算&#xff1a; 使用ArcGIS…

1.1 数据采集总览

正所谓巧妇难为无米之炊&#xff0c;数据采集是数据处理的第一步。 什么是数据采集 数据采集&#xff0c;也称为数据收集&#xff0c;是将原始数据从各种来源获取并存储起来的过程。这个过程是数据分析和数据仓库建设的第一步&#xff0c;涉及到从不同的数据源中提取数据&…

Element-UI实现el-dialog弹框拖拽功能

在实际开发中&#xff0c;会发现有些系统&#xff0c;弹框是可以在浏览器的可见区域自由拖拽的&#xff0c;这极大方便用户的操作。但在查看Element-UI中弹框&#xff08;el-dialog&#xff09;组件的文档时&#xff0c;发现并未实现这一功能。不过也无须担心&#xff0c;vue中…

搜索引擎数据库介绍

搜索引擎数据库的定义 搜索引擎数据库是一类专门用于数据内容搜索的NoSQL数据库&#xff0c;是非结构化大数据处理分析领域中重要的角色。搜索引擎数据库使用索引对数据中的相似特征进行归类&#xff0c;并提高搜索能力。通过对索引和检索过程的优化&#xff0c;以处理大量文本…

前后端经验分享:秋招春招赛道如何选择

前言&#xff1a;考研考公&#xff1f;国企互联网&#xff1f;老白小粉也曾对未来的方向选择产生迷茫&#xff0c;但最终老白小粉都选择了就业 →前端春招秋招经验分享 →后端春招秋招经验分享 因此今天这篇文章主要针对秋招春招的就业赛道给予学弟学妹们一些建议。 对于计算机…

【深度学习系列】全面指南:安装TensorFlow的CPU和GPU版本

本博客旨在为初学者提供一份全面的指南&#xff0c;介绍如何根据个人电脑的配置选择并安装适合的TensorFlow版本。内容涵盖了如何查看电脑显卡型号以确定是安装CPU还是GPU版本的TensorFlow&#xff0c;创建Python虚拟环境&#xff0c;以及使用conda命令查找可用的TensorFlow版本…

厂里资讯之异步通知文章上下架

kafka及异步通知文章上下架 1)自媒体文章上下架 需求分析 2)kafka概述 消息中间件对比 特性ActiveMQRabbitMQRocketMQKafka开发语言javaerlangjavascala单机吞吐量万级万级10万级100万级时效性msusmsms级以内可用性高&#xff08;主从&#xff09;高&#xff08;主从&#…