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.mzph.cn/bicheng/32560.shtml

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

相关文章

前端面试题日常练-day81 【面试题】

题目 希望这些选择题能够帮助您进行前端面试的准备&#xff0c;答案在文末 在Sass中&#xff0c;以下哪个功能用于创建一个颜色列表&#xff1f; a) extend b) for c) import d) color Sass中的父选择器&#xff08;Parent Selector&#xff09;是通过以下哪个符号表示的&…

【Oracle】实验一 安装和使用Oracle数据库

【实验目的】 掌握Oracle软件安装过程&#xff0c;选择安装组件掌握建立Oracle数据库&#xff0c;配置网络连接使用SQL*Plus&#xff0c;登录到实例和数据库掌握命令方式的关闭和启动实例及数据库 【实验内容】 安装Oracle19c&#xff0c;记录安装过程。切记&#xff1a;创建…

自然语言处理学习路线(1)——NLP的基本流程

NLP基本流程 【NLP基本流程】 0. 获取语料 ——> 1. 语料预处理 ——> 2. 特征工程&选择 ——> 3. 模型训练 ——> 4. 模型输出&上线 【NLP基本流程图】 Reference 1. 自然语言处理(NLP)的一般处理流程&#xff01;-腾讯云开发者社区-腾讯云 2. …

js函数声明与函数表达式的区别

在JavaScript中&#xff0c;函数可以通过函数声明和函数表达式两种方式进行定义。 函数声明是通过关键字function和函数名来定义的&#xff0c;例如&#xff1a; function add(a, b) {return a b; }函数表达式是将函数赋值给一个变量或者存储在一个对象的属性中&#xff0c;…

数组初了解

一.引入 现在&#xff0c;有一个场景需求&#xff0c;我们需要将10个数字存入&#xff0c;也就是10个变量。但如果场景需求改变&#xff0c;是用户输入了10个数&#xff0c;让我们求里面的最大值。那10个变量就显得过于臃肿。 我们需要一个新的数据结构&#xff0c;来装一系列…

贪心推公式——AcWing 125. 耍杂技的牛

贪心推公式 定义 贪心算法是一种在每一步选择中都采取在当前状态下最优的选择&#xff0c;希望通过局部的最优选择来得到全局最优解的算法策略。 运用情况 问题具有最优子结构&#xff0c;即一个问题的最优解包含其子问题的最优解。可以通过局部最优决策逐步推导到全局最优…

stm32学习笔记---GPIO输入(理论部分)

目录 GPIO输入模式下的硬件和电路 按键原理 传感器原理 什么是上下拉电阻&#xff1f; 运算放大器当做比较器 按键的硬件电路 传感器的硬件电路 STM32用到的C语言知识 STM32中的C语言数据类型 C语言中的宏定义 typedef和define的区别是什么&#xff1f; C语言的枚举…

计算机基础之:硬件系统的性能评估标准

服务器时钟的性能通常涉及多个方面&#xff0c;主要包括准确性、稳定性、以及对系统性能的影响。以下是一些关键指标和衡量方法&#xff1a; 准确性&#xff1a; 时间偏移&#xff1a;测量服务器时钟与一个可靠时间源&#xff08;如GPS时间、原子钟或NTP服务器&#xff09;之间…

Python itertools模块

itertools 是 Python 标准库中的一个模块&#xff0c;它提供了许多用于操作迭代对象的工具函数。这些函数可以高效地生成迭代器&#xff0c;用于处理序列和集合&#xff0c;特别适用于循环和组合数学。以下是 itertools 模块中一些常用函数的概述&#xff1a; 一、无限迭代器 i…

如何理解广角镜头和长焦镜头的区别。

为什么广角镜头的视野会比长焦镜头的视野大呢&#xff1f; 我之前用等光程解释了景深&#xff0c;也解释了为什么焦距越远&#xff0c;成像越大&#xff0c;但是从来没有提到过视野范围这个概念。实际上在我之前建立的数学模型中&#xff0c;物曲面S是无限大的&#xff0c;像曲…

保护您的机密:Foxit Reader PDF文件加密与解密全攻略

保护您的机密&#xff1a;Foxit Reader PDF文件加密与解密全攻略 引言 在数字化时代&#xff0c;保护敏感信息的安全比以往任何时候都更为重要。PDF文件作为一种流行的文档格式&#xff0c;广泛用于存储和交换数据。Foxit Reader不仅提供了阅读PDF的功能&#xff0c;还具备强…

掌握Emacs Verilog Mode:高效硬件开发指南

掌握Emacs Verilog Mode&#xff1a;高效硬件开发指南 引言 在硬件开发领域&#xff0c;Emacs Verilog Mode是一个强大的工具&#xff0c;它为Verilog硬件描述语言提供了专业的编辑支持。通过与Emacs的其他模式和工具集成&#xff0c;Verilog Mode不仅增强了代码编辑的效率&a…

管综 之 逻辑

1.复言命题 1.1假言推理 1.命题模型识别:当题干中出现如果那么&#xff0c;只有才&#xff0c;当且仅当等典型关联词时此题考的是简单假言推理问题 2.三步解题法:1️⃣:画箭头 2️⃣:递否 3️⃣:找答案 口诀&#xff1a; [口诀1]充分条件前推后 [口诀2]逆否命题等价于原命题 […

一加全机型TWRP合集/橙狐recovery下载-20240603更新-支持一加12/Ace3V手机

TWRP是目前安卓平台的刷机神器&#xff0c;可快速刷写第三方ROM或官方系统&#xff0c;刷入TWRP之前需要解锁BL&#xff0c;目前已适配一加多个机型。ROM乐园小编20240603整理&#xff0c;涵盖一加1到一加Ace3V多机型专用TWRP文件&#xff0c;个人机型橙狐recovery适配相对完整…

systemd在程序被kill -9时的动作

现象 今天在测试程序的时候发现&#xff0c;使用kill -9杀死程序之后&#xff0c;程序的资源回收动作依旧被执行了。 分析 执行 kill -9 abc&#xff0c;然后立即再执行ps -ef | grep abc&#xff0c;发现此时多了一个父进程为1的进程&#xff0c;正在执行abc service中定义…

自制HTML5游戏《贪吃蛇》

一、游戏简介 贪吃蛇是一款经典的电子游戏&#xff0c;最早在1976年由Gremlin公司推出&#xff0c;名为"Blockade"。游戏的玩法简单却富有挑战性&#xff0c;玩家控制一条蛇在封闭的场地内移动&#xff0c;通过吃食物增长身体&#xff0c;同时避免撞到自己的身体或场…

第3章 小功能大用处-Bitmaps、HyperLogLog、GEO

1.Bitmaps 1.1数据结构模型 现代计算机用二进制&#xff08;位&#xff09;作为信息的基础单位&#xff0c;1个字节等于8位&#xff0c;例 如“big”字符串是由3个字节组成&#xff0c;但实际在计算机存储时将其用二进制表 示&#xff0c;“big”分别对应的ASCII码分别是98、10…

22.智能指针(下)

标题 五、引用计数智能指针5.1 共享引用计数智能指针共享数据5.2 使用Box定义三个共享链表5.3 使用Rc代替Box5.4 引用计数增加实验 六、RefCell和内部可变性模式6.1 通过RefCell在运行时检查借用规则6.2 内部可变性&#xff1a;不可变值的可变借用1&#xff09;内部可变性的用例…

mysql数据库中模拟程序循环执行sql命令快速造数命令

解决复杂问题不可能通过一个 SQL 语句完成&#xff0c;我们需要执行多个 SQL 操作。流程控制语句的作用就是控 制存储过程中 SQL 语句的执行顺序&#xff0c;是我们完成复杂操作必不可少的一部分。只要是执行的程序&#xff0c;流程 就分为三大类&#xff1a; 顺序结构 &#x…

论文《Universal Graph Convolutional Networks》笔记

【UGCN】论文提出一个基本问题&#xff0c;即是否不同的网络结构属性应该采用不同的传播机制。通过实验发现&#xff0c;对于完全同配性、完全异配性和随机性的网络&#xff0c;1-hop、2-hop和k-nearest neighbor&#xff08;kNN&#xff09;邻居分别更适合作为信息传播的邻域。…