C++协程

简单的协程

#include <iostream>   // 包含标准输入输出流头文件
#include <thread>     // 包含线程支持头文件
#include <coroutine>  // 包含协程支持头文件
#include <future>     // 包含异步操作支持头文件
#include <chrono>     // 包含时间库头文件
#include <functional> // 包含函数对象头文件// 定义一个名为 Result 的结构体
struct Result{// 定义一个 promise_type 结构体struct promise_type {// 返回一个 Result 对象Result get_return_object() { return {}; }// 定义协程的初始挂起点std::suspend_never initial_suspend() { return {}; }// 定义协程的最终挂起点std::suspend_never final_suspend() noexcept { return {}; }// 协程的返回值类型为 voidvoid return_void() {}// 未处理的异常处理函数void unhandled_exception() {}};
};// 定义一个全局的协程句柄
std::coroutine_handle<> coroutine_handle;// 定义一个可等待对象结构体
struct AWaitableObject
{// 默认构造函数AWaitableObject() {}// 定义 await_ready 函数,表示是否准备好bool await_ready() const { return false; }// 定义 await_resume 函数,表示恢复时的返回值int await_resume() { return 0; }// 定义 await_suspend 函数,表示挂起协程时的操作void await_suspend(std::coroutine_handle<> handle){// 保存协程句柄coroutine_handle = handle;}
};// 定义一个协程函数
Result CoroutineFunction()
{// 打印开始协程的信息std::cout << "start coroutine\n";// 等待可等待对象int ret = co_await AWaitableObject(); // 打印完成协程的信息std::cout << "finish coroutine\n";
}// 主函数
int main()
{// 打印开始的信息std::cout << "start \n"; // 调用协程函数auto coro = CoroutineFunction();// 打印协程 co_await 的信息std::cout << "coroutine co_await\n"; // 恢复协程coroutine_handle.resume();// 返回 0 表示程序正常结束return 0;
}

co_await 是 C++20 引入的一种新的操作符,用于支持协程的异步等待。co_await 操作符的使用需要等待一个可等待对象,该对象需要实现三个特定的成员函数或通过重载对应的操作符。这三个成员函数分别是 await_ready(), await_suspend(), 和 await_resume()。我们来看一下在你的代码中 co_await AWaitableObject() 是如何工作的:

  1. await_ready:

    bool await_ready() const { return false; }
    
    • 这个函数返回一个布尔值,表示这个对象是否已经准备好。如果返回 true,协程将不会被挂起,直接继续执行后续代码。如果返回 false,协程将被挂起,直到这个对象准备好。
    • 在你的代码中,await_ready 总是返回 false,所以协程会被挂起。
  2. await_suspend:

    void await_suspend(std::coroutine_handle<> handle) {coroutine_handle = handle;
    }
    
    • 这个函数在协程被挂起时被调用。它接受一个 std::coroutine_handle 作为参数,表示当前协程的句柄。
    • 在你的代码中,它将协程句柄保存到全局变量 coroutine_handle 中。这允许你在以后手动恢复这个协程。
  3. await_resume:

    int await_resume() { return 0; }
    
    • 这个函数在协程恢复时被调用。它的返回值将成为 co_await 表达式的结果。
    • 在你的代码中,它返回 0

现在我们具体来看 co_await AWaitableObject(); 在你的代码中的执行流程:

  1. 进入 CoroutineFunction 函数:

    std::cout << "start coroutine\n";
    
    • 打印 “start coroutine”。
  2. 执行 co_await AWaitableObject():

    • 创建一个 AWaitableObject 对象。
    • 调用 AWaitableObjectawait_ready 方法,返回 false,因此协程挂起。
    • 调用 AWaitableObjectawait_suspend 方法,将协程句柄保存到全局变量 coroutine_handle 中。
    • 协程挂起,控制权返回到调用方 main 函数。
  3. 回到 main 函数:

    std::cout << "coroutine co_await\n";
    
    • 打印 “coroutine co_await”。
  4. 恢复协程:

    coroutine_handle.resume();
    
    • 手动恢复协程,调用 await_resume 方法,返回 0
  5. 继续执行 CoroutineFunction:

    std::cout << "finish coroutine\n";
    
    • 打印 “finish coroutine”。

整个过程展示了协程的挂起和恢复机制,通过 co_await 实现异步操作。AWaitableObject 作为一个可等待对象,实现了协程所需的三个成员函数,协调了协程的挂起和恢复。

多个任务

#include <chrono>
#include <coroutine>
#include <deque>
#include <iostream>
#include <windows.h>
std::deque<std::coroutine_handle<>> tasks;
// 简单的协程类
struct AsyncTask {struct promise_type {AsyncTask get_return_object() { return {}; }std::suspend_never initial_suspend() { return {}; }std::suspend_never final_suspend() noexcept { return {}; }void return_void() {}void unhandled_exception() {}};
};
struct AWaitableObject {int delay;AWaitableObject(int delay) : delay(delay) {}bool await_ready() const { return false; }int await_resume() { return 0; }void await_suspend(std::coroutine_handle<> handle) {tasks.push_back(handle);Sleep(delay);}
};
// 模拟异步任务1
AsyncTask task1() {co_await AWaitableObject(200);std::cout << "Task 1 completed" << std::endl;
}// 模拟异步任务2
AsyncTask task2() {co_await AWaitableObject(100);std::cout << "Task 2 completed" << std::endl;
}// 主函数
int main() {// 打印开始的信息std::cout << "main start \n";task1();task2();std::cout << "main continue\n";// 恢复协程while (!tasks.empty()) {auto task = tasks.front();tasks.pop_front();task.resume();}std::cout << "main completed" << std::endl;return 0;
}

推荐资料:
深入浅出c++协程

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

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

相关文章

试用笔记之-免费的汇通餐饮管理软件

首先下载免费的汇通餐饮管理软件&#xff1a; http://www.htsoft.com.cn/download/htcanyin.exe 安装后的图标 登录软件&#xff0c;默认没有密码 汇通餐饮管理软件主界面 汇通餐饮软件前台系统 点菜

eclipse断点调试(用图说话)

eclipse断点调试&#xff08;用图说话&#xff09; debug方式启动项目&#xff0c;后端调试bug调试 前端代码调试&#xff0c;请参考浏览器断点调试&#xff08;用图说话&#xff09; 1、前端 选中一条数据&#xff0c;点击删除按钮 2、后端接口打断点 断点按钮 介绍 resum…

前端知识点

HTML、CSS 相关 1、 BFC 1、BFC 是什么&#xff1f; BFC&#xff08;Block Formatting Context&#xff09; 格式化上下文&#xff1b; 指一个独立的渲染区域&#xff0c;或者说是一个隔离的独立容器&#xff1b;可以理解为一个独立的封闭空间。无论如何不会影响到它的外面 …

Elasticsearch-Rest-Client

Elasticsearch-Rest-Client&#xff1a;官方RestClient&#xff0c;封装了ES操作&#xff0c;API层次分明&#xff0c;上手简单。 1. 导入依赖 <dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>elasticsearch-rest-high…

BUG TypeError: GPT2Model.forward() got an unexpected keyword argument ‘past’

TypeError: GPT2Model.forward() got an unexpected keyword argument past’ 环境 transformers 4.38.1详情 这是由于新版的transformers 对GPT2Model.forward() 参数进行了改变导致的错误。具体是past名称改为了 past_key_values 。 解决方法 找到错误语…

【Windows】draw.io(免费的开源跨平台绘图软件)软件介绍

软件介绍 draw.io 是一款免费且易于使用的在线流程图绘图软件&#xff0c;后来更名为 diagrams.net。它最初作为一个基于 Web 的应用程序提供&#xff0c;支持用户创建各种类型的图表、流程图、网络图、组织结构图、UML 图等。它是完全免费的、强大的、专业的、易于使用的和高…

分享:Motionity-开源的Web端动画编辑器

Motionity是一个免费且开源的Web端动画编辑器&#xff0c;它结合了After Effects和Canva的优点&#xff0c;为用户提供了强大的动画编辑功能。支持视频剪切、图像搜索过滤、文本动画库、图层蒙版等功能。 一、项目背景与特点 开源项目&#xff1a;Motionity是一个开源项目&…

黄子韬vs徐艺洋卫生间风波

【热搜爆点】黄子韬VS徐艺洋&#xff1a;卫生间风波背后的职场与友情界限探讨在这个充满欢笑与意外的综艺时代&#xff0c;《跟我出游吧》再次以它独有的魅力&#xff0c;引爆了一个既尴尬又引人深思的话题——“黄子韬要上徐艺洋的卫生间&#xff1f;”这不仅仅是一句简单的调…

Yarn的安装与配置

Yarn 是一个快速、可靠且安全的 JavaScript 包管理器&#xff0c;最初由 Facebook 开发&#xff0c;旨在提供比 npm 更快的依赖安装速度和更一致的包管理体验。以下是 Yarn 的安装与配置教程&#xff1a; 安装 Yarn 方法 1: 使用 npm 安装 如果你的系统已经安装了 Node.js …

基于YOLOv10深度学习的CT扫描图像肾结石智能检测系统【python源码+Pyqt5界面+数据集+训练代码】深度学习实战、目标检测

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…

【ajax实战02】数据管理网站—验证码登录

一&#xff1a;数据提交&#xff08;提交手机验证码&#xff09; 核心思路整理 利用form-serialize插件&#xff0c;收集对象形式的表单数据后&#xff0c;一并提交给服务器。后得到返回值&#xff0c;进一步操作 基地址&#xff1a; axios.defaults.baseURL http://geek.…

Keil5 ST-LINK setting闪退问题解决

1. 官网下载新版驱动文件 MDK uVision crashes when using ST-Link debugger 2. 解压替换 STLinkUSBDriver6.1.2.0Signed 我的库文件目录&#xff1a; D:\Tool\Keil5\ARM\STLink

开源模型应用落地-FastAPI-助力模型交互-WebSocket篇(六)

一、前言 使用 FastAPI 可以帮助我们更简单高效地部署 AI 交互业务。FastAPI 提供了快速构建 API 的能力,开发者可以轻松地定义模型需要的输入和输出格式,并编写好相应的业务逻辑。 FastAPI 的异步高性能架构,可以有效支持大量并发的预测请求,为用户提供流畅的交互体验。此外,F…

【JS】纯web端使用ffmpeg实现的视频编辑器-视频合并

纯前端实现的视频合并 接上篇ffmpeg文章 【JS】纯web端使用ffmpeg实现的视频编辑器 这次主要添加了一个函数&#xff0c;实现了视频合并的操作。 static mergeArgs(timelineList) {const cmd []console.log(时间轴数据,timelineList)console.log("文件1",this.readD…

MatLab三维图形绘制基础

三维图形绘制 三维曲线 plot3 螺旋图绘制 % %三维图像:螺旋图绘制 clear; clc; t [0:0.1:10*pi];% 向量 x sin(t) t.*cos(t);%t是向量&#xff0c;用点乘 y cos(t) - t.*sin(t); z t; plot3(x,y,z); grid on;plot3 绘制同型矩阵 %% % plot3绘制同型矩阵 t [0:0.1:10*…

游戏AI的创造思路-技术基础-tanh函数详解

又来搞事情&#xff0c;总想着把sigmoid函数替换成其他函数作为激活函数&#xff0c;或者找到更合适某一段训练的函数&#xff0c;所以今天来聊聊tanh函数&#xff08;谁让咱当年差点去了数学系&#xff0c;结果还是在数学系转过去计算机的&#xff09; 目录 3.9. tanh函数详解…

【Rust基础入门】Hello Cargo

文章目录 前言Cargo是什么&#xff1f;Cargo的作用查看cargo版本使用cargo创建项目Cargo.toml文件cargo build命令cargo runcargo check为发布构建 总结 前言 在Rust编程中&#xff0c;Cargo扮演着至关重要的角色。它是Rust的包管理器&#xff0c;负责处理许多任务&#xff0c…

uniapp入门

一、新建项目 进入到主界面&#xff0c;左上角点击新建——1.项目 输入项目名称&#xff0c;Vue版本选择3 二、创建页面 选中左侧文件目录里的pages文件夹&#xff0c;右键&#xff0c;选择新建页面 1输入名称 2选中“创建同名目录” 3选择模板&…

昇思25天学习打卡营第7天|网络构建

网络构建 神经网络模型由tensor操作和神经网络层构成。 MIndSporezhong&#xff0c;Cell是构建所有网络的基类&#xff0c;也是网络的基本单元。cell也由子cell构成。 定义模型类 # 继承nn.Cell类 class Network(nn.Cell):def __init__(self):super().__init__()self.flatte…

ElasticSearch 和 MySQL的区别

MySQLElasticSearch 数据库&#xff08;database&#xff09;索引&#xff08;index&#xff09;数据表&#xff08;table&#xff09; 类型&#xff08;type&#xff09; 记录文档&#xff08;document&#xff0c;json格式&#xff09; 一、ES基础命令 1. ES cat查询命令 2.…