新闻中心

C++怎么实现一个简单的协程库_C++协程编程与自定义协程实现

2025-11-10
浏览次数:
返回列表
C++20协程通过co_await、co_yield、co_return实现轻量级并发。核心组件包括coroutine_handle、promise_type和awaiter。示例中simple_task演示基本协程结构,初始与结束均挂起,需手动resume分阶段执行。generator模板支持co_yield,实现惰性求值的迭代器模式,适用于范围生成等场景。通过自定义promise_type可扩展异步行为。

c++怎么实现一个简单的协程库_c++协程编程与自定义协程实现

协程(Coroutine)是一种比线程更轻量的并发编程模型,能够在执行过程中主动挂起和恢复。C++20 正式引入了协程支持,通过关键字 co_awaitco_yieldco_return 实现异步逻辑的同步写法。下面介绍如何基于 C++20 实现一个简单的协程库,帮助理解其底层机制。

理解协程的基本组件

C++20 的协程依赖三个核心部分:协程句柄(coroutine_handle)、承诺对象(promise_type)和awaiter对象。编译器在遇到 co_await 等关键字时会生成状态机代码,开发者需要提供这些组件的实现来控制协程行为。

一个最简协程类型通常包含:

  • promise_type:定义协程内部状态,决定 co_return/co_yield 行为。
  • get_return_object():协程启动时返回给调用者的对象。
  • initial_suspend():协程开始是否立即挂起。
  • final_suspend():协程结束时是否挂起。
  • unhandled_exception():异常处理逻辑。

实现一个简单的 task 协程类型

我们实现一个简易的 task 类型,支持 co_return 并能被等待执行完成。

示例代码如下:

#include <coroutine>
#include <iostream>

struct simple_task {
    struct promise_type {
        simple_task get_return_object() {
            return simple_task{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() {}
    };

    using handle_type = std::coroutine_handle<promise_type>;

    explicit simple_task(handle_type h) : coro(h) {}
    ~simple_task() { if (coro) coro.destroy(); }

    handle_type coro;
};

simple_task hello_coroutine() {
    std::cout << "Hello, ";
    co_await std::suspend_always{};
    std::cout << "Coroutine!\n";
}

上面代码中,hello_coroutine 函数返回一个 simple_task 对象。它在初始和结束时都挂起,可用于手动恢复执行。

手动调度协程执行

由于我们使用了 std::suspend_always,协程创建后不会自动运行,需要显式 resume。

例如:

Yaara Yaara

使用AI生成一流的文案广告,电子邮件,网站,列表,博客,故事和更多…

Yaara 95 查看详情 Yaara
int main() {
    auto t = hello_coroutine(); // 创建协程,但暂停在初始位置
    std::cout << "Before resume\n";
    t.coro.resume(); // 恢复执行到第一个挂起点后
    t.coro.resume(); // 继续执行到结束
    return 0;
}

输出结果为:

Before resume
Hello, 
Coroutine!

这说明协程可以分阶段执行,适合用于异步任务调度。

扩展支持 co_yield 与 generator

若想实现类似 Python 的生成器功能,可定义一个 generator 类型:

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 {}; }
        std::suspend_always yield_value(T v) {
            value = v;
            return {};
        }
        void return_void() {}
        void unhandled_exception() {}
    };

    using handle_type = std::coroutine_handle<promise_type>;

    explicit generator(handle_type h) : coro(h) {}
    ~generator() { if (coro) coro.destroy(); }

    bool next() { // 移动到下一个值
        if (!coro || coro.done()) return false;
        coro.resume();
        return !coro.done();
    }

    T value() { return coro.promise().value; }

private:
    handle_type coro;
};

使用方式:

generator<int> range(int from, int to) {
    for (int n = from; n < to; ++n) {
        co_yield n;
    }
}

int main() {
    for (auto g = range(1, 5); g.next(); ) {
        std::cout << g.value() << ' ';
    }
    std::cout << '\n';
    return 0;
}

输出:1 2 3 4

这个 generator 支持惰性求值,每次调用 next 才计算下一个值。

基本上就这些。通过自定义 promise_type 和 awaiter,你可以构建出各种协程语义,比如自动销毁、链式调用、future 风格返回等。C++ 协程虽语法复杂,但一旦掌握,就能写出高效且清晰的异步代码。

以上就是C++怎么实现一个简单的协程库_C++协程编程与自定义协程实现的详细内容,更多请关注其它相关文章!


# ai  # python  # 是一种  # 分阶段  # 结束时  # 链式  # 挂起  # 自定义  # 异步任务  # 并发编程  # stream  # ios  # c++  # 扫码点单营销推广策略  # 卫辉网站建设平台有哪些  # 家政行业网站建设运营  # 怎么在网上接单网站推广  # 合伙人网站建设  # 基层网站建设调研报告  # 重庆做营销网站建设  # 家装网站推广哪个好  # 师宗网站建设程序  # 惠州网站优化加盟  # 求值  # 句柄  # 就能  # 你可以 


相关栏目: 【 科技资讯46185 】 【 网络学院92790


相关推荐: LINUX的perf命令入门_LINUX官方性能分析工具的使用与解读  拼多多购物车商品数量无法修改如何处理 拼多多购物车操作优化方法  React/Next.js中实现列表项的动态移动与状态管理:兼论唯一键的重要性  在J*a中如何开发在线活动报名与管理系统_活动报名管理项目实战解析  Win10双系统截图高效法 截屏快捷键速记【技巧】  如何使 Jest 模拟函数默认抛出错误以提高测试效率  J*aScript中正确使用querySelectorAll与复杂CSS选择器  win11开机启动修复循环怎么办 Win11无法进入系统高级启动解决方法【修复】  使用J*aScript检测输入元素是否包含在特定类中  极兔快递快件信息查询系统 极兔快递官网运单号追踪  一加 Nord 5 隐私权限异常_一加 Nord 5 系统安全优化  c++如何使用TBB库进行任务并行_c++ Intel线程构建模块  React Router 嵌套组件中 URL 重定向问题的解决方案  深入理解J*aScript中的B样条曲线与节点向量生成  Composer中的^和~符号代表什么_精通Composer版本号语义化约束  怎么去除衣服上的口红印_生活小妙招教你用酒精轻松擦除  Descript怎样用AI剪辑自动去噪_Descript用AI剪辑自动去噪【自动降噪】  天猫2025双十一0点秒杀攻略 天猫爆款抢购时间  LINUX怎么设置定时任务_LINUX crontab配置教程  css滚动动画效果怎么实现_使用Animate.css滚动触发动画类  腾讯QQ邮箱官方网站_QQ邮箱网页版在线登录  Win10快速启动功能利弊分析 Win10开启或关闭快速启动教程【技巧】  在命令行怎么运行html项目_命令行运行html项目方法【教程】  Go语言中Map存储的结构体如何调用指针方法:深入解析与实践  将HTML Canvas内容转换为可上传的图像文件(File对象)  格力空气能E5故障代码是什么情况_格力空气能E5代码解析与应对措施  React中useState与局部变量:理解组件状态管理与渲染机制  sublime如何配置Go语言开发环境_sublime搭建Golang编译运行系统  ArrayList与LinkedList核心操作的Big-O复杂度分析  Golang如何通过reflect操作map_Golang reflect map操作与遍历技巧  windows10怎么关闭系统提示音_windows10彻底静音设置方法  微博网页版怎么开启两步验证_微博网页版账号安全两步验证设置方法  网站内容防复制粘贴的实现策略与局限性  汽水音乐在线版入口_汽水音乐网页播放手册  顺丰国际快递查询 国际件官方查询入口  高德地图公交到站提醒失败如何解决 高德提醒权限设置  “音游” × “怪文书” 题材的节奏冒险游戏 《晕晕电波症候群》确定于2026年4月发售!  谷歌google账号注册详细步骤 谷歌账号注册官方教程  Python中高效访问嵌套字典与列表中的键值对  葱吃多了会怎样 葱吃多了会伤胃吗  痛风发作了怎么办? 快速止痛和后期饮食调理  如何使用CaptainHook和Composer管理Git钩子_在提交前自动运行代码检查的Composer配置  steam官方网页快速访问 steam账号注册全流程  实现全屏滚动与导航点:专业教程  新三国志曹操传110级星符试炼夏侯渊极难攻略  夸克浏览器图书入口 夸克手机浏览器阅读入口  如何在Promise链中有效终止错误处理后的执行  解决 MongoDB 聚合查询中对象数组 _id 匹配问题  铁路12306的积分有效期是多久_铁路12306积分有效期说明  钉钉视频会议画面卡顿如何解决 钉钉会议画面优化方法 

搜索