当前位置: 首页 > news >正文

C++ 的协程

现代C++中的协程(coroutines)是C++20引入的一项重大语言特性,它们允许函数在执行过程中可以暂停并稍后从暂停点恢复执行。协程提供了一种控制流机制,使得函数可以包含多个入口点和出口点,这与传统的单入口、单出口的函数模型形成了鲜明对比。

协程的核心思想是“可恢复的函数”,即在执行过程中,函数可以“挂起”其执行状态,并在将来的某个时间点“恢复”执行。这种机制使得编写异步代码变得更加直观和易于管理,因为你可以使用类似于同步代码的结构来表达异步操作。

在C++中,协程通过特定的语法和一组标准库组件来实现。以下是一些关键点:

  1. 协程句柄(coroutine handle)
    协程句柄是一个轻量级的对象,它封装了与协程执行相关的状态和控制信息。你可以使用协程句柄来暂停、恢复或销毁协程。

  2. 协程承诺类型(promise type)
    每个协程都有一个与之关联的承诺类型(通常是一个模板类),它定义了协程的返回类型和状态。承诺类型负责在协程挂起和恢复时管理其状态,并处理与协程相关的异常和返回值。

  3. co_awaitco_yieldco_return
    这三个关键字是C++协程语法的核心。co_await用于挂起协程并等待一个awaitable对象的完成;co_yield用于在生成器中逐个产生值;co_return用于从协程返回结果。

  4. 标准库支持
    C++20标准库提供了一些与协程相关的组件,如std::suspend_alwaysstd::suspend_neverstd::coroutine_handle等,以及用于定义协程行为的模板类(如std::generatorstd::async_generator,尽管这些可能在未来的标准中有所变化或扩展)。

  5. 异步编程
    协程最显著的应用之一是异步编程。通过协程,你可以编写看起来像是同步调用的异步代码,从而简化异步操作的复杂性。

  6. 生成器
    协程还可以用于实现生成器,即按需产生一系列值的函数。这与迭代器类似,但生成器允许更复杂的逻辑和状态管理。

  7. 实现细节
    协程的实现涉及编译器对特定语法结构的支持,以及标准库提供的底层机制。编译器需要识别协程函数,并在编译时生成适当的代码来处理协程的挂起和恢复。

使用协程涉及几个关键步骤,包括定义协程函数、使用特定的协程语法(如co_awaitco_yieldco_return),以及可能定义自定义的promise类型来管理协程的状态和返回值。以下是一个基本的指南,帮助你开始在现代C++中使用协程。

1. 编译器支持

首先,确保你的编译器支持C++20协程。GCC 10及以上版本、Clang 11及以上版本以及MSVC(Visual Studio 2019版本16.6及以上)都提供了对C++20协程的支持。

2. 包含必要的头文件

在你的C++源文件中包含必要的头文件。对于基本的协程功能,你可能需要包含<coroutine>头文件。

#include <coroutine>

3. 定义协程函数

协程函数使用co_awaitco_yield(对于生成器)或co_return来控制其执行流程。下面是一个简单的例子,展示了如何使用co_await来挂起和恢复协程的执行。

#include <coroutine>
#include <iostream>
#include <thread>
#include <chrono>// 一个简单的awaitable对象,它会在一段时间后“完成”
struct simple_awaitable {bool await_ready() const noexcept { return false; } // 协程需要挂起void await_suspend(std::coroutine_handle<>) const noexcept {} // 挂起时的操作(这里为空)void await_resume() const noexcept {} // 恢复时的操作(这里为空)// 模拟异步等待(例如,I/O操作)static simple_awaitable await_now() { return {}; }
};// 协程函数示例
struct MyCoroutine {struct promise_type {MyCoroutine get_return_object() { return MyCoroutine{std::coroutine_handle<promise_type>::from_promise(*this)}; }std::suspend_always initial_suspend() { return {}; }std::suspend_always final_suspend() noexcept { return {}; }void return_void() {}void unhandled_exception() { std::exit(1); } // 处理异常(这里简单退出程序)};std::coroutine_handle<promise_type> handle;MyCoroutine(std::coroutine_handle<promise_type> h) : handle(h) {}~MyCoroutine() { if (handle) handle.destroy(); }void resume() { handle.resume(); }
};MyCoroutine example_coroutine() {std::cout << "Before await\n";co_await simple_awaitable::await_now(); // 挂起协程std::cout << "After await\n";
}int main() {auto coro = example_coroutine();std::cout << "Main thread continues\n";std::this_thread::sleep_for(std::chrono::seconds(1)); // 模拟主线程做一些其他工作coro.resume(); // 恢复协程的执行return 0;
}

4. 使用协程

在上面的例子中,example_coroutine是一个协程函数,它使用co_await来挂起其执行。在main函数中,我们创建了协程对象coro,并在稍后通过调用coro.resume()来恢复其执行。

5. 自定义promise类型(可选)

在上面的例子中,我们定义了MyCoroutine结构和一个简单的promise_type来管理协程的状态。对于更复杂的协程,你可能需要定义自己的promise类型来处理返回值、异常和协程的生命周期。

6. 注意事项

  • 协程是编译器和语言特性的结合,因此确保你的编译器和标准库支持C++20协程。
  • 协程的状态管理是通过promise类型来实现的,因此理解promise类型的工作原理对于编写有效的协程至关重要。
  • 协程的异步性质意味着它们可以与其他线程交互,因此需要注意线程安全和同步问题。
  • 尽管C++20引入了协程的基本框架和语法,但协程的完整功能和最佳实践仍在不断发展和完善中。因此,在使用协程时,建议查阅最新的C++标准文档和编译器文档,以获取最新的信息和最佳实践。

相关文章:

C++ 的协程

现代C中的协程&#xff08;coroutines&#xff09;是C20引入的一项重大语言特性&#xff0c;它们允许函数在执行过程中可以暂停并稍后从暂停点恢复执行。协程提供了一种控制流机制&#xff0c;使得函数可以包含多个入口点和出口点&#xff0c;这与传统的单入口、单出口的函数模…...

D3的竞品有哪些,D3的优势,D3和echarts的对比

D3 的竞品 ECharts: 简介: ECharts 是由百度公司开发的一款开源的 JavaScript 图表库&#xff0c;提供了丰富的图表类型和高度定制化的配置选项。特点: 易于使用&#xff0c;文档详尽&#xff0c;社区活跃&#xff0c;支持多种图表类型&#xff08;如折线图、柱状图、饼图、散点…...

大厂计算机网络高频八股文面试题及参考答案(面试必问,持续更新)

目录 请简述 TCP 和 UDP 的区别? TCP 和 UDP 分别对应的常见应用层协议有哪些? UDP 的优缺点是什么?它适用于哪些场景? UDP 如何实现可靠传输? 请简述 HTTP 和 HTTPS 的区别? HTTP 协议的工作原理是什么? HTTP 状态码有哪些常见的类型及其含义? HTTP 哪些常用的…...

【bayes-Transformer-GRU多维时序预测】多变量输入模型。matlab代码,2023b及其以上

% 1. 数据准备 X_train 训练数据输入; Y_train 训练数据输出; X_test 测试数据输入; % 2. 模型构建 inputSize size(X_train, 2); numHiddenUnits 100; numResponses 1; layers [ … sequenceInputLayer(inputSize) biLSTMLayer(numHiddenUnits, ‘OutputMode’, ‘se…...

动手学深度学习69 BERT预训练

1. BERT 3亿参数 30亿个词 在输入和loss上有创新 两个句子拼起来放到encoder–句子对 cls-class分类 sep-seperate 分隔符 分开每个句子 告诉是哪个句子 两个句子给不同的向量 位置编码不用sin cos&#xff0c; 让网络自己学习 bert–通用任务 encoder 是双向的&#xff0c;…...

【2024软考架构案例题】你知道 Es 的几种分词器吗?Standard、Simple、WhiteSpace、Keyword 四种分词器你知道吗?

&#x1f449;博主介绍&#xff1a; 博主从事应用安全和大数据领域&#xff0c;有8年研发经验&#xff0c;5年面试官经验&#xff0c;Java技术专家&#xff0c;WEB架构师&#xff0c;阿里云专家博主&#xff0c;华为云云享专家&#xff0c;51CTO 专家博主 ⛪️ 个人社区&#x…...

Elman 神经网络 MATLAB 函数详解

Elman 神经网络 MATLAB 函数详解 一、引言 Elman 神经网络是一种在时间序列分析和动态系统建模领域广泛应用的递归神经网络&#xff08;RNN&#xff09;。MATLAB 提供了一系列强大的函数来创建、训练和应用 Elman 神经网络&#xff0c;使得用户能够方便地利用其处理具有时间序…...

vue el-date-picker 日期选择器禁用失效问题

当value-format"yyyy-MM-dd"的格式不要改为"yyyyMMdd"&#xff0c;否则会导致日期选择器禁用失效问题&#xff0c;因为该组件默认的格式就是yyyy-MM-dd。 <el-col v-for"(item, index) in formData" :key"index" ><el-date-…...

搭建Python2和Python3虚拟环境

搭建Python3虚拟环境 1. 更新pip2. 搭建Python3虚拟环境第一步&#xff1a;安装python虚拟化工具第二步&#xff1a; 创建虚拟环境 3. 搭建Python2虚拟环境第一步&#xff1a;安装虚拟环境模块第二步&#xff1a;创建虚拟环境 4. workon命令管理虚拟机第一步&#xff1a;安装扩…...

【HarmonyOS NEXT】一次开发多端部署(以轮播图、Tab栏、列表为例,配合栅格布局与媒体查询,进行 UI 的一多开发)

关键词&#xff1a;一多、响应式、媒体查询、栅格布局、断点、UI 随着设备形态的逐渐增多&#xff0c;应用界面适配也面临着很大问题&#xff0c;在以往的安卓应用开发过程中&#xff0c;往往需要重新开发一套适用于大屏展示的应用&#xff0c;耗时又耗力&#xff0c;而鸿蒙提供…...

ubontu--cuDNN安装

1. 下载 cuDNN https://developer.nvidia.com/cudnn 2. 拷贝到服务器/home/<username>文件夹下 解压缩到当前文件夹&#xff1a; tar -xvf cudnn-linux-x86_64-9.5.1.17_cuda11-archive.tar.xz复制头文件和库文件到cuda安装目录/usr/local/cuda/ sudo cp /home/usern…...

高项 - 项目范围管理

个人总结&#xff0c;仅供参考&#xff0c;欢迎加好友一起讨论 博文更新参考时间点&#xff1a;2024-12 高项 - 章节与知识点汇总&#xff1a;点击跳转 文章目录 高项 - 项目范围管理范围管理ITO规划监控 管理基础产品范围与项目范围管理新实践 5大过程组与范围管理过程概述裁…...

如何获取PostgreSQL慢查询?从小白到高手的实战指南

数据库优化是性能调优的核心&#xff0c;而慢查询则是性能瓶颈的罪魁祸首。如何找到慢查询并优化它们&#xff0c;是每个开发者和DBA都必须掌握的技能。 今天&#xff0c;我们就来聊聊如何在PostgreSQL中快速获取慢查询日志&#xff0c;并结合不同场景进行分析优化。本文风格参…...

golang分布式缓存项目 Day4 一致性哈希

注&#xff1a;该项目原作者&#xff1a;https://geektutu.com/post/geecache-day1.html。本文旨在记录本人做该项目时的一些疑惑解答以及部分的测试样例以便于本人复习 为什么使用一致性哈希 我该访问谁 对于分布式缓存来说&#xff0c;当一个节点接收到请求&#xff0c;如…...

ARM 汇编指令

blr指令的基本概念和用途 在 ARM64 汇编中&#xff0c;blr是 “Branch with Link to Register” 的缩写。它是一种分支指令&#xff0c;主要用于跳转到一个由寄存器指定的地址&#xff0c;并将返回地址保存到链接寄存器&#xff08;Link Register&#xff0c;LR&#xff09;中。…...

打造个性化体验:在Axure中创建你的专属组件库

打造个性化体验&#xff1a;在Axure中创建你的专属组件库 在数字产品设计的浪潮中&#xff0c;效率和一致性是设计团队追求的两大圣杯。 随着项目的不断扩展&#xff0c;重复性的工作逐渐增多&#xff0c;设计师们开始寻找能够提高工作效率、保持设计一致性的解决方案。 而 …...

如何用WordPress和Shopify提升SEO表现?

选择合适的建站程序对于SEO优化非常重要。目前&#xff0c;WordPress和Shopify是两种备受推崇的建站平台&#xff0c;各有优势。 WordPress最大的优点是灵活性。它支持大量SEO插件&#xff0c;帮助你调整元标签、生成站点地图、优化内容结构等。这些功能让你能够轻松地提升网站…...

不泄密的安全远程控制软件需要哪些技术

在数字化浪潮中&#xff0c;远程控制软件已不再是简单的辅助工具&#xff0c;而是成为企业运作和日常工作中不可或缺的一部分。随着远程办公模式的广泛采纳&#xff0c;这些软件提供了一种既安全又高效的途径来管理和访问远端系统。无论是在家办公、技术支持还是远程教育&#…...

rust高级特征

文章目录 不安全的rust解引用裸指针裸指针与引用和智能指针的区别裸指针使用解引用运算符 *&#xff0c;这需要一个 unsafe 块调用不安全函数或方法在不安全的代码之上构建一个安全的抽象层 使用 extern 函数调用外部代码rust调用C语言函数rust接口被C语言程序调用 访问或修改可…...

STM32F407简单驱动步进电机(标准库)

配置 单片机型号&#xff1a;STM32F104ZGT6 步进电机&#xff1a;YK28HB40-01A 驱动器&#xff1a;YKD2204M-Plus 接线方式&#xff1a; pu&#xff1a;接对应的产生PWM的引脚&#xff0c;这里接PF9&#xff0c;对应TIM14_CH1通道&#xff01; pu-&#xff1a;接单片机的G…...

基于FPGA的PID算法学习———实现PID比例控制算法

基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容&#xff1a;参考网站&#xff1a; PID算法控制 PID即&#xff1a;Proportional&#xff08;比例&#xff09;、Integral&#xff08;积分&…...

跨链模式:多链互操作架构与性能扩展方案

跨链模式&#xff1a;多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈&#xff1a;模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展&#xff08;H2Cross架构&#xff09;&#xff1a; 适配层&#xf…...

Qt Http Server模块功能及架构

Qt Http Server 是 Qt 6.0 中引入的一个新模块&#xff0c;它提供了一个轻量级的 HTTP 服务器实现&#xff0c;主要用于构建基于 HTTP 的应用程序和服务。 功能介绍&#xff1a; 主要功能 HTTP服务器功能&#xff1a; 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...

现代密码学 | 椭圆曲线密码学—附py代码

Elliptic Curve Cryptography 椭圆曲线密码学&#xff08;ECC&#xff09;是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础&#xff0c;例如椭圆曲线数字签…...

OpenLayers 分屏对比(地图联动)

注&#xff1a;当前使用的是 ol 5.3.0 版本&#xff0c;天地图使用的key请到天地图官网申请&#xff0c;并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能&#xff0c;和卷帘图层不一样的是&#xff0c;分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...

【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论

路径问题的革命性重构&#xff1a;基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中&#xff08;图1&#xff09;&#xff1a; mermaid graph LR A((A)) --- B((B)) B --- C((C)) C --- D((D)) D --- A A -.- C[无直接路径] B -…...

免费数学几何作图web平台

光锐软件免费数学工具&#xff0c;maths,数学制图&#xff0c;数学作图&#xff0c;几何作图&#xff0c;几何&#xff0c;AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...

【网络安全】开源系统getshell漏洞挖掘

审计过程&#xff1a; 在入口文件admin/index.php中&#xff1a; 用户可以通过m,c,a等参数控制加载的文件和方法&#xff0c;在app/system/entrance.php中存在重点代码&#xff1a; 当M_TYPE system并且M_MODULE include时&#xff0c;会设置常量PATH_OWN_FILE为PATH_APP.M_T…...

【p2p、分布式,区块链笔记 MESH】Bluetooth蓝牙通信 BLE Mesh协议的拓扑结构 定向转发机制

目录 节点的功能承载层&#xff08;GATT/Adv&#xff09;局限性&#xff1a; 拓扑关系定向转发机制定向转发意义 CG 节点的功能 节点的功能由节点支持的特性和功能决定。所有节点都能够发送和接收网格消息。节点还可以选择支持一个或多个附加功能&#xff0c;如 Configuration …...

【LeetCode】算法详解#6 ---除自身以外数组的乘积

1.题目介绍 给定一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O…...