0

0

C++如何实现简易的协程任务链?(then/await风格)

冰火之心

冰火之心

发布时间:2026-02-26 10:29:12

|

161人浏览过

|

来源于php中文网

原创

std::coroutine_handle不能直接链式调用then,因为c++20协程仅提供挂起/恢复机制,不内置任务调度与组合语义;需手动管理handle生命周期、状态流转及唤醒逻辑,并通过封装task类实现安全链式await。

c++如何实现简易的协程任务链?(then/await风格)

为什么 std::coroutine_handle 不能直接链式调用 then

因为 C++20 协程本身不提供任务调度或组合语义,co_await 是挂起/恢复机制,不是“自动续跑”。你写 task.then([]{...}),底层没地方存这个回调,也没触发时机——除非你自己管调度、状态流转和唤醒逻辑。

常见错误现象:segmentation fault 或静默不执行,往往是因为 coroutine_handle 被销毁后还被尝试 .resume(),或者唤醒时目标协程已结束但没检查 .done()

  • 必须显式保存前一个协程的 coroutine_handle,并在它结束时手动唤醒下一个
  • 每个 then 回调需包装成新协程(用 promise_type 控制生命周期)
  • 不能依赖栈变量捕获:lambda 捕获的局部对象在父协程挂起后可能已析构

怎么让 then 返回可 co_await 的对象

核心是定义一个轻量级 task wrapper,比如 Task<t></t>,它内部持有 coroutine_handle<promise_type></promise_type>,且 promise_type 实现 get_return_object()initial_suspend()final_suspend()。重点在于 then 方法返回新的 Task<u></u>,并把当前 task 的完成事件绑定到新协程的启动上。

实操建议:

立即学习C++免费学习笔记(深入)”;

  • then 内部用 co_spawn 类似逻辑:新建协程,挂起等待前序完成,再执行回调
  • 避免在 then 中直接 co_await 原始 handle;要用封装后的 Task,它能保证 await_ready() 判断是否已完成
  • 回调函数必须是 noexcept 或妥善处理异常,否则会调用 std::terminate

示例关键片段:

情感家园企业站5.0 多语言多风格版
情感家园企业站5.0 多语言多风格版

一套面向小企业用户的企业网站程序!功能简单,操作简单。实现了小企业网站的很多实用的功能,如文章新闻模块、图片展示、产品列表以及小型的下载功能,还同时增加了邮件订阅等相应模块。公告,友情链接等这些通用功能本程序也同样都集成了!同时本程序引入了模块功能,只要在系统默认模板上创建模块,可以在任何一个语言环境(或任意风格)的适当位置进行使用!

下载
template<typename T>
struct Task {
  struct promise_type {
    Task get_return_object() { return Task{coroutine_handle<promise_type>::from_promise(*this)}; }
    suspend_never initial_suspend() { return {}; }
    suspend_always final_suspend() noexcept { return {}; }
    void unhandled_exception() { std::terminate(); }
    void return_value(T v) { value = std::move(v); }
    std::optional<T> value;
  };
  // ...
};

co_await 一个 Task 时到底发生了什么

本质是调用了 Task::operator co_await(),它返回一个 awaiter 对象。该 awaiter 的 await_ready() 检查协程是否已结束(handle.done()),await_suspend() 把当前协程 handle 注册为前序 task 完成时的唤醒目标,await_resume() 返回结果值。

容易踩的坑:

  • 忘记在 await_suspend() 中保存当前 handle:导致唤醒丢失,协程永远挂起
  • await_ready() 返回 trueawait_resume() 还没准备好数据(比如 value 未赋值)→ UB
  • 多个 co_await 同一个 Task 实例:第二次 await 时协程已结束,done() 为 true,但若没缓存结果,可能读到未初始化值

性能和兼容性要注意哪些硬约束

协程帧分配方式直接影响能否安全链式调用:std::coroutine_handle 默认栈分配不可靠,必须用堆分配(如 operator newpromise_type::operator new 中重载),否则 then 创建的新协程可能因栈展开而失效。

编译器支持现状(截至 GCC 13 / Clang 16 / MSVC 19.35):

  • MSVC 对 co_await 表达式中临时对象生命周期处理最保守,建议显式命名中间 Task 变量
  • Clang 在 -O2 下可能优化掉未使用的 coroutine_handle,导致 await_suspend 接收空 handle
  • 所有编译器都不支持跨线程直接 resume 同一个协程 handle,then 回调若需切线程,必须走外部调度器(如 asio::post

最易被忽略的一点:Task 移动构造函数必须正确转移 coroutine_handle 并置空原 handle,否则双重 resume 或 double-free。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

294

2025.08.29

C++中int、float和double的区别
C++中int、float和double的区别

本专题整合了c++中int和double的区别,阅读专题下面的文章了解更多详细内容。

105

2025.10.23

lambda表达式
lambda表达式

Lambda表达式是一种匿名函数的简洁表示方式,它可以在需要函数作为参数的地方使用,并提供了一种更简洁、更灵活的编码方式,其语法为“lambda 参数列表: 表达式”,参数列表是函数的参数,可以包含一个或多个参数,用逗号分隔,表达式是函数的执行体,用于定义函数的具体操作。本专题为大家提供lambda表达式相关的文章、下载、课程内容,供大家免费下载体验。

213

2023.09.15

python lambda函数
python lambda函数

本专题整合了python lambda函数用法详解,阅读专题下面的文章了解更多详细内容。

192

2025.11.08

Python lambda详解
Python lambda详解

本专题整合了Python lambda函数相关教程,阅读下面的文章了解更多详细内容。

60

2026.01.05

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

425

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

597

2023.08.10

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

425

2023.07.18

batoto漫画官网入口与网页版访问指南
batoto漫画官网入口与网页版访问指南

本专题系统整理batoto漫画官方网站最新可用入口,涵盖最新官网地址、网页版登录页面及防走失访问方式说明,帮助用户快速找到batoto漫画官方平台,稳定在线阅读各类漫画内容。

331

2026.02.25

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
10分钟--Midjourney创作自己的漫画
10分钟--Midjourney创作自己的漫画

共1课时 | 0.1万人学习

Midjourney 关键词系列整合
Midjourney 关键词系列整合

共13课时 | 0.9万人学习

AI绘画教程
AI绘画教程

共2课时 | 0.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号