C++,什么是协程?

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

本文介绍了 C++20 中的协程。协程是可暂停和恢复执行的特殊函数,常用于异步编程等场景。文中阐述了协程的核心概念,如挂起、恢复等,介绍了 C++20 协程的关键组件,给出了生成器和异步任务示例,还说明了协程简化异步编程等优势。

在这里插入图片描述


1. 协程(Coroutine)简介

协程是一种特殊的函数,可以在执行过程中暂停并在稍后恢复执行。与普通函数不同,协程可以在任意点挂起(yield)并将控制权返回给调用者,同时保留其状态,以便后续恢复执行。协程常用于异步编程、生成器、状态机等场景。

C++20 引入了对协程的原生支持,使得开发者可以更方便地编写协程代码。


2. 协程的核心概念

  1. 挂起(Suspend):

    • 协程可以在执行过程中挂起,将控制权返回给调用者。

    • 挂起时,协程的状态(局部变量、执行位置等)会被保存。

  2. 恢复(Resume):

    • 协程可以从挂起的位置恢复执行,继续运行。
  3. 协程帧(Coroutine Frame):

    • 协程的状态(局部变量、挂起点等)存储在协程帧中。

    • 协程帧在堆上分配,生命周期由协程库管理。

  4. 协程句柄(Coroutine Handle):

    • 用于控制协程的执行(挂起、恢复、销毁等)。

3. C++20 协程的关键组件

  1. co_await:

    • 用于挂起协程,等待某个操作完成。

    • 操作可以是异步 I/O、定时器、任务等。

  2. co_yield:

    • 用于生成值并挂起协程。

    • 常用于实现生成器(Generator)。

  3. co_return:

    • 用于从协程返回值并结束协程。
  4. 协程类型:

    • 协程函数必须返回一个符合协程接口的类型(如 std::future、generator 等)。

4. 协程示例

4.1 示例 1:简单的协程(生成器)

以下示例实现了一个生成器,用于生成一系列整数。

#include <iostream>
#include <coroutine>

// 定义一个生成器类型
template<typename T>
struct Generator {
    struct promise_type {
        T value; // 生成的值
        Generator get_return_object() { return Generator{std::coroutine_handle<promise_type>::from_promise(*this)}; }
        std::suspend_always initial_suspend() { return {}; } // 初始挂起
        std::suspend_always final_suspend() noexcept { return {}; } // 最终挂起
        void unhandled_exception() { std::terminate(); } // 异常处理
        std::suspend_always yield_value(T val) { value = val; return {}; } // 挂起并返回值
        void return_void() {} // 协程结束
    };

    std::coroutine_handle<promise_type> handle;

    explicit Generator(std::coroutine_handle<promise_type> h) : handle(h) {}
    ~Generator() { if (handle) handle.destroy(); } // 销毁协程

    T next() {
        handle.resume(); // 恢复协程
        return handle.promise().value; // 返回生成的值
    }
};

// 定义一个生成器协程
Generator<int> range(int start, int end) {
    for (int i = start; i <= end; ++i) {
        co_yield i; // 生成值并挂起
    }
}

int main() {
    auto gen = range(1, 5); // 创建生成器
    for (int i = 0; i < 5; ++i) {
        std::cout << gen.next() << std::endl; // 获取生成的值
    }
    return 0;
}

输出:

1
2
3
4
5

4.2 示例 2:异步任务

以下示例实现了一个简单的异步任务,模拟异步操作。

#include <iostream>
#include <coroutine>
#include <thread>
#include <chrono>

// 定义一个异步任务类型
struct AsyncTask {
    struct promise_type {
        int value; // 任务的结果
        AsyncTask get_return_object() { return AsyncTask{std::coroutine_handle<promise_type>::from_promise(*this)}; }
        std::suspend_always initial_suspend() { return {}; } // 初始挂起
        std::suspend_always final_suspend() noexcept { return {}; } // 最终挂起
        void unhandled_exception() { std::terminate(); } // 异常处理
        void return_value(int val) { value = val; } // 返回值
    };

    std::coroutine_handle<promise_type> handle;

    explicit AsyncTask(std::coroutine_handle<promise_type> h) : handle(h) {}
    ~AsyncTask() { if (handle) handle.destroy(); } // 销毁协程

    int get() {
        handle.resume(); // 恢复协程
        return handle.promise().value; // 返回结果
    }
};

// 定义一个异步任务协程
AsyncTask computeAsync() {
    std::cout << "Starting async computation..." << std::endl;
    std::this_thread::sleep_for(std::chrono::seconds(2)); // 模拟耗时操作
    co_return 42; // 返回结果
}

int main() {
    auto task = computeAsync(); // 创建异步任务
    std::cout << "Waiting for result..." << std::endl;
    int result = task.get(); // 获取结果
    std::cout << "Result: " << result << std::endl;
    return 0;
}

输出:

Starting async computation...
Waiting for result...
Result: 42

5. 协程的优势

  1. 简化异步编程:

    • 协程可以将异步代码写成同步风格,避免回调地狱。
  2. 高效的状态管理:

    • 协程的状态由编译器自动管理,无需手动维护状态机。
  3. 灵活的控制流:

    • 协程可以挂起和恢复,适用于生成器、流处理等场景。

6. 总结

  • 协程是一种可以挂起和恢复的函数,适用于异步编程、生成器等场景。

  • C++20 引入了原生协程支持,通过 co_await、co_yield 和 co_return 实现协程逻辑。

  • 协程的核心是协程帧和协程句柄,用于保存状态和控制执行。

  • 通过生成器和异步任务的示例,可以更好地理解协程的用法和优势。

参考

【1】到底该怎么理解协程?
【2】[C++] 协程初步:手把手教你写一个协程

c++20协程基础概念 c++协程 阅读详情

相关推荐

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/C++实现协程及原理(详细完整版)-架构师篇

一、协程(Coroutine)简介 协程,又称微线程,纤程。英文名Coroutine。 协程的概念很早就提出来了,但直到最近几年才在某些语言(如Lua)中得到广泛应用。 子程序,或者称为函数,在所有语言中都是层级调用,比如A调用B,B在执行过程中又调用了C,C执行完毕返回,B执行完毕返回,最后是A执行完毕。 所以子程序调用是通过栈实现的,一个线程就是执行一个子程序。 子程序调用总是一个入口,一次返回,调用顺序是明确的。而协程的调用和子程序不同。 协程看上去也是子程序,但执行过程中,在子程序内部可中断,然后转

嵌入式Linux内核的博客 1万+

【编程语言】协程比较

在Java中,并没有内建的协程支持。项目Loom是在进行中的实验性项目,旨在给Java添加轻量级的并发机制,它将引入一称为“fibers”的新概念来实现协程,目的是提供比线程更加高效的并发模型。由于C++协程的底层性质,使用起来比较复杂,但提供了极高的自定义空间,适合需要高性能协程控制的场景。C++在C++20标准中新增了对协程的支持,其协程模型是一个底层的构建块,提供了很多灵活性和控制能力。C++ 的协程功能强大但相对复杂,给了开发者更多底层操作的能力和灵活性,适合对性能有严格要求的场景。

数字人生 1647

C++协程

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

平凡 6568

深入LSM6DSL的FIFO连续模式:基于STM32和MEMS库的数据流高效处理指南

本文深入探讨了LSM6DSL的FIFO连续模式,结合STM32硬件平台和ST官方MEMS库,提供了高效的数据流处理方案。通过优化I2C通信时序、中断驱动设计以及动态ODR调整,实现低功耗数据采集与处理,显著提升嵌入式传感器应用的性能和续航能力。

weixin_30387799的博客 348

汇川伺服驱动器参数优化实战指南

本文详细介绍了汇川伺服驱动器参数优化的实战技巧,涵盖控制模式选择、电子齿轮比调整、刚性匹配与振动抑制等关键内容。通过实际案例和实用技巧,帮助工程师快速掌握伺服驱动器参数调校方法,提升设备运行精度和稳定性。特别针对高精度定位和高速响应场景提供了专业指导。

weixin_29070721的博客 733

项目——C++协程库

当你有很多协程时,如何把这些协程都消耗掉,这就是协程调度。未实现协程调度,对于每个协程,都需要用户手动调用协程的resume方法将协程运行起来,然后等协程运行结束并返回,再运行下一个协程。这种运行协程的方式其实是用户自己在挑选协程执行,相当于用户在充当调度器,显然不够灵活.引入协程调度后,则可以先创建一个协程调度器,然后把这些要调度的协程传递给调度器,由调度器负责把这些协程一个一个消耗掉。1. 继承自协程调度器Scheduler,支持协程调度的全部功能。除了协程调度,IO协程调度还增加了IO事件调度。

qq_44736340的博客 2761

SpyGlass Lint脚本实战:如何用TCL自动化RTL代码检查(附完整配置模板)

本文详细介绍了如何利用TCL脚本实现SpyGlass Lint工具的自动化RTL代码检查。通过构建模块化、工程化的脚本框架,文章提供了从环境搭建、核心配置、规则定制到豁免管理的完整实战指南,并附有可复用的配置模板,旨在帮助IC设计工程师构建高效、一致的代码质量检查流水线。

weixin_29204205的博客 134

2505C++,py和go调用雅兰亭库的协程工具

2505C++,py和go调用雅兰亭库的协程工具

个人进步之路 1024

Redis架构演进:从主从、哨兵到集群,如何支撑亿级流量的秒杀场景?

本文深入探讨了分布式缓存Redis的三种核心高可用模式:主从复制、哨兵模式与集群模式。以高并发的电商秒杀业务为切入点,我们分析了每种模式的优缺点和适用场景,并最终选择Redis集群模式作为最佳解决方案。文章提供了基于Spring Boot和Spring Data Redis的完整实现代码,详细展示了如何配置和使用Redis集群来应对高并发、高可用的挑战,旨在帮助开发者在实际项目中做出正确的技术选型和架构设计。

lingRJ777的博客 723

PADS VX2.4差分对设置避坑指南:常见错误与解决方案

本文深度解析了在PADS VX2.4中进行高速PCB设计时,差分对设置的核心要点与常见陷阱。针对Layout规则设置、Router布线实战中的阻抗控制、线长匹配等关键环节,提供了具体的避坑指南和解决方案,帮助工程师确保信号完整性,提升设计质量。

weixin_29216049的博客 359

C++、Java、Go三种语言创建线程/协程对比

创建线程/协程执行多任务,应该是我们作为程序猿,一定会遇到的场景,下面就分别贴出三种的语言的使用方式,哪一种是你的菜?

happyinter9527的博客 778

ros_gz_bridge__镜像__readme

Run。

1113

2603C++,简单实现协程

2603C++,简单实现协程

个人进步之路 321

SAP 系统里生成 PDF 的几条主干路径:从 Spool 转换到 Adobe 原生渲染,再到 BTP 云服务

本文系统梳理了SAP生态中PDF生成的多种技术方案,包括Spool转换、OTF转换、Smart Forms/Adobe Forms原生生成以及云端服务等不同路径。文章通过实际案例和代码示例,详细分析了各方案的适用场景、技术要点和工程实践建议,特别强调了多语言支持、字体处理、性能优化等关键因素。针对不同业务需求,提供了从简单导出到复杂交互式PDF的完整解决方案框架,为SAP环境下的PDF处理提供了实用指南。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 283

YOLO十年演进:从CNN到Transformer再到MoE,我看懂了2026年目标检测的落地风向标

技术永远是为业务服务的,能解决真实问题的技术,才是有价值的。YOLO的十年演进,从CNN到Transformer再到MoE,从来都不是学术上的炫技,而是一步一步解决工业落地的痛点:从让实时检测成为可能,到解决复杂场景的漏检误检,再到打破精度和算力的死局,每一步都踩在了工业落地的真实需求上。很多新入行的朋友,总喜欢追新,今天换Transformer,明天堆MoE,觉得模型越新、参数越大,就越厉害。

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 748

2404C++,C++协程选择

2404C++,C++协程选择

个人进步之路 305

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

2507C++,C++协程的发送者

2507C++,C++协程的发送者

个人进步之路 1213

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

2403C++,C++20协程库

2403C++,C++20协程库

个人进步之路 1471

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

2403C++,C++11玩转无栈协程

2403C++,C++11玩转无栈协程

个人进步之路 713

2401C++,无栈协程核心概念

2401C++,无栈协程核心概念

个人进步之路 606

2311C++,协程实现异步读写

2311C++,协程实现异步读写

个人进步之路 735

2403C++,C++20协程通道

2403C++,C++20协程通道

个人进步之路 647

2508C++,融合py和C++的协程1

2508C++,融合py和C++的协程1

个人进步之路 1215

2508C++,融合py和C++的协程3

2508C++,融合py和C++的协程3

个人进步之路 562

2508C++,融合py和C++的协程2

2508C++,融合py和C++的协程1

个人进步之路 519
上一篇: candb++ windows11运行报错,找不到mfc140.dll
下一篇: C++,设计模式,【目录篇】
智驾
博客等级 码龄11年 6669粉丝 574原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

智驾

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值