C++20 协程(coroutine)

C++20 协程coroutine #1.协程概念 协程函数与普通函数的区别: (1)普通函数执行完返回,则结束。 协程函数可以运行到一半,返回并保留上下文;下次唤醒时恢复上下文,可以接着执行。 协程与多线程: (1)协程适合IO密集型程序,一个线程可以调度执行成千上万的协程,IO事件不会阻塞线程 (2)多线程适合CPU密集型场景,每个线程都负责cpu计算,cpu得到充分利用 协程与异步: (1)都是不阻塞线程的编程方式,但是协程是用同步的方式编程、实现异步的目的,比较适合代码编写、阅读和理解 (2)异步编程通常使用callback 阅读详情

C++20加入协程,其实是为了以后加入网络库而准备的。协程也是异步执行的,那么它跟std::thread有什么区别呢?区别在于协程是用户调度的,线程则是系统调度的。由于是用户态的,所以协程数量是不受限制的,想要多少就创建多少。同时C++20的协程是无栈协程,在调度切换时性能比线程快很多。基于协程的特点,基本上协程就是为了网络库而服务的了。应用开发者不建议使用协程,除非你明确知道协程的优势所在,否则不建议使用协程(std::async不香吗)。

  • 传统异步调用

协程出现以前,异步函数也许是这么写的

using AsyncResultsCallback = std::function<void(const std::string&)>;

// 异步获取结果函数
void async_get_results(AsyncResultsCallback callback) {
    std::thread t([callback]() {
        std::this_thread::sleep_for(std::chrono::seconds(3));   // 模拟耗时的操作
        callback("seconds later");
    });
    t.detach(); // 测试代码,实际项目中不要使用detach
}

调用方式

async_get_results([] (const std::string& str){
        std::cout<<"async get results: "<<str<<std::endl;
    });
  • 协程的使用例子

协程一般需要定义三个东西:协程体(coroutine),协程承诺特征类型(Traits),await对象(await)。

要调用协程,首先得定义协程体。

协程体的定义和普通函数一样,但是协程体里面有co_await、co_return、co_yield关键字。也就是说只要函数体里面带有co_await、co_return、co_yield三个关键字中的一个,那么这个函数体就是协程(coroutine)。先看看协程定义例子:

// 协程体
Traits coroutine_get_results(AsyncResultsCallback callback)
{
    // 这时还在主线程中
    std::cout<<"run at main thread id:"<<std::this_thread::get_id()<<std::endl;

    const std::string& ret = co_await AsyncResultsWaitable();

    // 这时已经是在子线程中了
    std::cout<<"run at slaver thread id:"<<std::this_thread::get_id()<<std::endl;
    callback(ret);
}

协程体定义和执行规则跟函数体是不一样的!这点一定要明确,否则你可能理解不了协程的写法

Traits并不是返回类型,而是协程的特征类型。协程体里面的语句可能会在不同的线程中执行,这个是最大的特点!co_await以后就在await对象的await_suspend(如果await_ready返回false)函数去执行了。等co_await语句执行完之后,这时候可能已经是在另一条线程中了。

再看下协程特征类型的定义:

// 给协程体使用的承诺特征类型
struct Traits
{
    struct promise_type {
        // 协程体被创建时被调用
        auto get_return_object() {
            return Traits{};
        }

        // get_return_object之后被调用
        auto initial_suspend() {
            return std::suspend_never{};
        }

        // return_void之后被调用
        auto final_suspend() {
            return std::suspend_never{};
        }

        void unhandled_exception() {
            std::terminate();
        }

        // 协程体执行完之后被调用
        void return_void() {
        }
    };
};

协程特征类型主要是用于一些事件的响应。

在看下await对象的定义:

// 协程使用的await对象
struct AsyncResultsWaitable
{
    // await是否已经计算完成,如果返回true,则co_await将直接在当前线程返回
    bool await_ready() const {
        return false;
    }

    // await对象计算完成之后返回结果
    std::string await_resume() {
        return _result;
    }

    // await对象真正调异步执行的地方,异步完成之后通过handle.resume()来是await返回
    void await_suspend(std::coroutine_handle<> handle)
    {
        async_get_results([handle, this] (const std::string& str) {
            _result = str;
            handle.resume();
        });
    }

    std::string _result; // 将返回值存在这里
};

await_ready:用来判断当前await对象是否已经计算完成,如果返回false则await_suspend将不会被调用co_await语句也将直接返回结果。

await_resume:用来返回await对象的计算结果。

await_suspend: await对象正在执行异步操作的地方。

协程调用例子:

    // 通过协程异步获取结果
    coroutine_get_results([] (const std::string& str){
        std::cout<<"coroutine get results: "<<str<<std::endl;
    });

附上整个测试程序源码,编译环境 gcc 10.1:

#include <iostream>
#include <functional>
#include <future>
#include <thread>
#include <string>
#include <coroutine>

using AsyncResultsCallback = std::function<void(const std::string&)>;

// 异步获取结果函数
void async_get_results(AsyncResultsCallback callback) {
    std::thread t([callback]() {
        std::this_thread::sleep_for(std::chrono::seconds(3));   // 模拟耗时的操作
        callback("seconds later");
    });
    t.detach(); // 测试代码,实际项目中不要使用detach
}

// 给协程体使用的承诺特征类型
struct Traits
{
    struct promise_type {
        // 协程体被创建时被调用
        auto get_return_object() {
            return Traits{};
        }

        // get_return_object之后被调用
        auto initial_suspend() {
            return std::suspend_never{};
        }

        // return_void之后被调用
        auto final_suspend() {
            return std::suspend_never{};
        }

        void unhandled_exception() {
            std::terminate();
        }

        // 协程体执行完之后被调用
        void return_void() {
        }
    };
};

// 协程使用的await对象
struct AsyncResultsWaitable
{
    // await是否已经计算完成,如果返回true,则co_await将直接在当前线程返回
    bool await_ready() const {
        return false;
    }

    // await对象计算完成之后返回结果
    std::string await_resume() {
        return _result;
    }

    // await对象真正调异步执行的地方,异步完成之后通过handle.resume()来是await返回
    void await_suspend(std::coroutine_handle<> handle)
    {
        async_get_results([handle, this] (const std::string& str) {
            _result = str;
            handle.resume();
        });
    }

    std::string _result; // 将返回值存在这里
};

// 协程体
Traits coroutine_get_results(AsyncResultsCallback callback)
{
    // 这时还在主线程中
    std::cout<<"run at main thread id:"<<std::this_thread::get_id()<<std::endl;

    const std::string& ret = co_await AsyncResultsWaitable();

    // 这时已经是在子线程中了
    std::cout<<"run at slaver thread id:"<<std::this_thread::get_id()<<std::endl;
    callback(ret);
}

int main(int argc, char *argv[])
{
    // 传统异步获取结果
    async_get_results([] (const std::string& str){
        std::cout<<"async get results: "<<str<<std::endl;
    });

    // 通过协程异步获取结果
    coroutine_get_results([] (const std::string& str){
        std::cout<<"coroutine get results: "<<str<<std::endl;
    });

    getchar();
    return 1;
}

 

最后,如果有不对的地方恳请大家多多指正,先谢谢了

C++20中的协程(Coroutine)功能解析:co_await C++20 协程的co_await实现 阅读详情

相关推荐

C++20中的协程(Coroutine)

目录C++20中的协程(Coroutine)那么,什么是协程?那么这么好用的协程,是不是只要C++20一推出,我们加上一个关键字就能直接把异步调用转化为同步调用呢?协程函数和Awaitable类那么,到底要如何使用协程呢?写在最后 C++20中的协程(Coroutine) 从2017年开始, 协程(Coroutine)的概念就开始被建议加入C++20的标准中了,并已经开始有人对C++20协程的提案进行了介绍。1事实上,协程的概念在很早就出现了,甚至其他语言(JS,Python,C#等)早就已经支持了协程。

Ninsun的博客 1万+

C++20协程

C++ 20 协程

2937

【并发编程二十一:终章】c++20协程( co_yield、co_return、co_await )

对比代码中的备注,我们知道协程开始时,在协程的状态对象分配内存后,调用promise_type的构造函数为协程的状态对象分配内存失败时构造成功后开始执行在以上函数后执行协程结束前执行出现未经处理的异常时执行co_return 时执行,return_void跟return_value二选一co_yield时执行。

junxuezheng的博客 3117

C++20 协程

1. 简介 协程就是一个可以挂起执行,稍后再恢复执行的函数。 协程是无栈式的(stackless),协程挂起时会返回到调用者,且恢复执行所需的数据会分开存储,而不放在栈上。 只要一个函数包含 co_await、co_yield 或 co_return 关键字,则它就是协程。 一个协程关联有如下多个对象: promise 对象:在协程内部操作此对象,协程通过它提交返回值或异常; 协程句柄:在协程外部操作此对象,用于恢复协程的执行或销毁协程帧; 协程状态:在堆上分配的内部状态。 2. co_await 操

gaoZhuanMing的博客 3628

华为防火墙USG6000系列多ISP上网(通过WEB界面设置)

华为防火墙多ISP上网,内网分区上网。内网多网段不同上网方式。

daxihe880的博客 1万+

IST——In-System-Test

安全性是自动驾驶平台的关键特性之一,而这些架构中使用的半导体芯片必须保证ISO 26262标准所要求的功能安全方面。为了监控由于现场缺陷导致的故障,在启动和/或关闭期间会自动运行系统内结构测试。当系统内测试(IST,In-System-Test)架构检测到任何永久性缺陷时,驾驶平台会做出响应,以实现系统的故障安全状态。汽车IC采用高质量测试方法进行筛选,以实现接近零的DPPM(每百万缺陷部件)。即使在这样的高测试标准下,由于环境或操作条件的影响,在系统现场运行过程中仍可能出现可靠性缺陷。

weixin_50518899的博客 3206

C++ 20 协程实战:coroutine 项目推荐

C++ 20 协程实战:coroutine 项目推荐 项目介绍 coroutine 是一个专注于 C++ 20 协程特性的开源项目,旨在帮助开发者深入理解和掌握 C++ 协程的使用。项目通过提供简洁且实用的设计示例,展示了如何在实际开发中应用协程技术。无论你是初学者还是经验丰富的开发者,coroutine 都能为你提供有价值的参考和学习资源。 项目技术分析 coroutine 项目充分利用了 C+...

gitblog_00683的博客 837

RT-DETR算法优化改进:轻量级上采样CARAFE算子 | 注意力机制大作战

上采样操作CARAFE,具有感受野大、内容感知、轻量级、计算速度快等优点,引入RT-DETR二次创新;1)代替Upsample进行使用;

①答疑群聊服务;②YOLO大模型知识问答系统;③计算机视觉论文生成智能体; 1265

【C++】C++20协程的await_transform和coroutine_handle

本文深入解析了C++20协程的核心机制,重点介绍了四个关键组件:std::coroutine_handle作为协程控制器、noop_coroutine空操作协程工具、await_transform等待转换器以及await_suspend挂起控制逻辑。文章通过代码示例展示了它们的具体用法,包括如何通过协程句柄控制协程生命周期、使用noop_coroutine作为安全占位符、利用await_transform拦截和转换等待表达式,以及await_suspend的三种返回值类型如何影响协程行为。最后提供了修正后的

Ape's IT Blog 508

【Android逆向工程】第18章:Ollvm 混淆与对抗

本章介绍了Ollvm混淆技术及其对抗方法。Ollvm是基于LLVM的开源代码混淆工具,主要实现控制流平坦化、虚假控制流和指令替换三种混淆技术。控制流平坦化通过状态变量和switch-case结构隐藏真实控制流,将原本清晰的逻辑拆分为多个状态块。混淆后的代码在静态分析中难以理解,但可通过动态追踪执行路径、符号执行等方法来还原原始逻辑。本章还提供了混淆代码示例和对抗策略,帮助理解Ollvm的工作原理及其防御方法。

w987333120的博客 213

51单片机入门指南-基于STC89C52(持续更新)

一、环境介绍 编程IDE: keil5 单片机型号: STC89C51/52 开发板: 普中科技的开发板 完整PDF资源下载地址:https://download.youkuaiyun.com/download/xiaolong1126626497/19785856 二、51单片机开发手册介绍 2.1 前言 51单片机是对所有兼容Intel 8031指令系统的单片机的统称。 该系列单片机的始祖是Intel的8004单片机,后来随着Flash rom技术的发展,8004单片机取得了长足的进展,成为应用最.

8797

C++ 20 协程 Coroutine

C++ 20 的协程是一个用于异步模型,主要用于服务开发的东东,由于概念和传统的同步变成有区别,同时自身的概念,接口,关键字很多。理解起来有点难度。C++ 20的协程是一个特殊的可以挂起,恢复(重入)的函数。协程内部可以出现三个关键字。co_await awaiter用于和等待体交互,可以挂起和恢复。co_yield 用于挂起协程,co_return用于返回。编译器通过返回值(类型result)里面result::promise(承诺对象)来识别什么函数是协程函数。

m0_73257876的博客 3534

YOLOv11改进策略【损失函数篇】| WIoU v3:针对低质量样本的边界框回归损失函数

是一种基于IoU的损失函数,旨在解决目标检测中边界框回归损失函数在处理低质量训练数据时的问题。论文链接:https://arxiv.org/pdf/2301.10051 源码链接:https://github.com/Instinct323/wiou此处需要查看的文件是中定义了模型的损失函数和计算方法,我们想要加入新的损失函数就只需要将代码放到这个文件内即可将下方的函数替换原本的函数即可: 用于计算各种损失。在内修改如下代码,使模型调用此损失函数。 tal.py中是一些损失函数的功能应用。在内修改如下代码,

Limiiiing的博客 3795

c++20 协程(coroutine)

c++20 协程(coroutine)

小x的博客 2401

NVIDIA Isaac GR00T N1 人形机器人强化学习入门教程(二)详细步骤

LeRobot 格式 1.1 加载数据集 要加载数据集,我们需要定义以下 3 项内容: 在数据中显示图像帧 我们还可以对 LeRobotSingleDataset 类中的数据进行一系列转换。下面展示了如何对数据进行转换。 现在看看应用转换后的数据有何不同。 例如,对状态和操作进行规范化和串联,对视频图像进行裁剪、调整大小和颜色抖动。 二、GR00T 推断 本教程介绍如何使用 GR00

2506_90492529的博客 3012

18、改进的LSTM用于污染物浓度预测

本文探讨了改进的长短期记忆网络(MLSTM)在空气污染预测中的应用,重点分析了其对印度泰米尔纳德邦五个城市(金奈、塞勒姆、哥印拜陀、马杜赖和图蒂科林)的PM2.5、PM10、SO2和NO2四种污染物浓度的预测效果。通过与传统LSTM模型的对比实验,结果显示MLSTM在预测准确性和执行效率方面均优于LSTM。研究结果表明,MLSTM在空气质量预测领域具有较高的应用潜力,可为环境保护和空气质量管理提供有力支持。

j0k1l2m3n的博客 175

C++20协程资源泄漏:coroutine_handle销毁时机与RAII解决方案

在异步编程中,协程通过挂起和恢复实现非阻塞操作,提升并发性能。其核心机制在于协程帧的生命周期管理,它承载了局部变量、状态等上下文信息。C++20协程通过std::coroutine_handle提供对协程帧的操控,但该句柄的析构并不自动释放协程帧内存,这构成了资源泄漏的常见根源。理解句柄销毁与帧销毁的分离原理至关重要,错误管理会导致内存、文件描述符等资源持续占用。在工程实践中,结合RAII(资源获取即初始化)模式包装句柄,明确所有权与销毁责任,是构建健壮异步系统的关键。本文聚焦于coroutine_hand

1039

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

C++20新特性—coroutine协程(一)

所谓“协程”,简单点说就是一个函数可以中止运行,待“条件成熟”后,再次在断点的地方重新运行,即能以“进入-暂停-继续-暂停…”这样的方式运行函数,因此讨论协程,需要关心下面几个问题: 在运行点暂停,然后再运行—暂停点的记录 暂停时的运行环境,恢复运行时,应首先恢复当时的环境—运行环境的记录 因协程状态是变化的,因此需要有办法查询协程当前的运行状态,包括返回值、异常等—协程状态的记录 异步操作是 “慢”资源与“快”资源协调编程方面的一个“老”问题,协程的目标就是试图以“同步的形式”编写出异步操作的效果。

guxch的专栏 2903

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

【C++20协程深度解析】:彻底掌握coroutine_handle重置的5大核心技巧

掌握C++20协程开发关键,深入解析coroutine_handle的重置机制。涵盖协程暂停恢复、资源管理、异常安全等场景,详解reset操作的核心原理与最佳实践,避免内存泄漏与悬空调用。提升协程控制力,值得收藏。

PixelShoal的博客 427

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

基于c++20 coroutine实现对称协程

简单总结就是对于每一个coroutine函数,都会生成一个专属的类,这个类的成员变量就是这个函数栈上的所有变量,在通过我们提供的promise_type和await的原语对这个类做拓展。我在其中做的最关键的一步就是在init时进行了suspend,同时suspend时存下父函数的handle,在这个协程被挂起时,handle被保存到全局变量,函数链被依次挂起返回到最上层。当协程执行完结束时,调用final_suspend,这时会直接通过我们保存父函数的handle,来唤醒父函数,从而实现协程的对称概念。

weixin_42162340的博客 723

异步革命:C++20 协程(<coroutine>)深度全解与实战指南

C++20协程:异步编程的革命性变革 C++20协程为异步编程带来了根本性变革,通过原生协程支持替代传统回调模式。协程提供轻量级用户态调度,仅需保存寄存器/栈指针,相比线程具有显著性能优势。标准库<coroutine>提供核心组件如coroutine_handle和协程Traits,但高层协程类型需自行实现。本文详细解析了生成器和异步任务的自定义实现方法,并介绍了Awaitable接口的设计。虽然C++20协程存在调试困难、无栈限制等问题,但其零堆分配、无上下文切换的特性使其成为高性能异步编程的

聚焦前沿科技与硬核技术底层拆解,深耕 AI、量子计算、WebAssembly 等核心领域,拒绝碎片化科普。以通俗语言讲透复杂原理,用干货内容拆解技术逻辑,助力从业者吃透核心、把握趋势,每篇都是可落地的深度技术沉淀。 1124

C++20新特性—coroutine协程(二)

下面一个示例说明co_await 的用法。 template<class T> struct generator { struct promise_type { std::suspend_never initial_suspend() const noexcept { std::cout<<"initial_suspend"<<std::endl; return {}; } std::suspend_never final_suspend()

guxch的专栏 1692

对于 C++:C++20中Concept(概念) 与 Coroutine(协程)的解析

C++20引入了概念(Concept)和协程(Coroutine)两大重要特性,显著提升了模板编程和异步编程的能力。概念解决了传统模板编程中使用SFINAE技术带来的代码晦涩、错误信息不友好等问题,通过声明式语法为模板参数添加约束条件。文章详细介绍了概念的定义方式、标准库预定义的概念分类,并展示了概念在实际编程中的应用示例。协程则提供了一种更高效的异步编程模型,允许函数暂停和恢复执行,避免了回调地狱和线程切换的开销。这两个特性共同构成了C++20最核心的语言改进,为开发者提供了更强大、更易用的编程工具。

2503_92929084的博客 304

C++20协程核心:std::coroutine_handle详解与实践

协程作为轻量级线程替代方案,通过挂起(suspend)和恢复(resume)机制优化异步编程。C++20标准引入的std::coroutine_handle是协程底层控制的核心接口,直接操作协程帧实现精细控制。该技术适用于需要手动调度协程、实现自定义异步框架等场景,但需注意生命周期管理以避免内存泄漏。结合RAII模式与智能指针可构建安全高效的协程系统,典型应用包括文件异步读取器、游戏AI状态机等。理解协程基础概念后,开发者能更高效地使用std::coroutine_handle进行高性能异步编程。

weixin_30437847的博客 323

C++20协程资源泄漏元凶(coroutine_handle销毁时机详解)

掌握coroutine_handle的销毁时机,避免C++20协程资源泄漏。详解协程生命周期管理、destroy调用时机与异常安全处理,揭示常见内存泄漏根源及规避策略。理解handle何时释放资源,提升协程稳定性,值得收藏。

InstrFun的博客 412

协程控制的关键所在,std::coroutine_handle在C++20中的实战应用全解析

掌握C++20协程控制核心,深入解析协程返回类型std::coroutine_handle的底层机制与实战应用。涵盖协程挂起、恢复、销毁等关键操作,适用于异步编程与任务调度场景,提升程序性能与可控性,值得收藏。

AlgoChat的博客 351
上一篇: C++20 新增库功能(Library Features)
下一篇: Linux中使用GitHub Desktop
BranchLin
博客等级 码龄10年 2粉丝 12原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值