新闻中心
C++怎么实现一个简单的协程库_C++协程编程与自定义协程实现
C++20协程通过co_await、co_yield、co_return实现轻量级并发。核心组件包括coroutine_handle、promise_type和awaiter。示例中simple_task演示基本协程结构,初始与结束均挂起,需手动resume分阶段执行。generator模板支持co_yield,实现惰性求值的迭代器模式,适用于范围生成等场景。通过自定义promise_type可扩展异步行为。

协程(Coroutine)是一种比线程更轻量的并发编程模型,能够在执行过程中主动挂起和恢复。C++20 正式引入了协程支持,通过关键字 co_await、co_yield 和 co_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
使用AI生成一流的文案广告,电子邮件,网站,列表,博客,故事和更多…
95
查看详情
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积分有效期说明
钉钉视频会议画面卡顿如何解决 钉钉会议画面优化方法


2025-11-10
浏览次数:次
返回列表
eam>
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";
}