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 并能被等待执行完成。
立即学习“C++免费学习笔记(深入)”;
示例代码如下:
#include #include struct simple_task { struct promise_type { simple_task get_return_object() { return simple_task{std::coroutine_handle::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; 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。
例如:
int main() { auto t = hello_coroutine(); // 创建协程,但暂停在初始位置 std::cout << "Before resumen"; t.coro.resume(); // 恢复执行到第一个挂起点后 t.coro.resume(); // 继续执行到结束 return 0;}
输出结果为:
Before resumeHello, Coroutine!
这说明协程可以分阶段执行,适合用于异步任务调度。
扩展支持 co_yield 与 generator
若想实现类似 Python 的生成器功能,可定义一个 generator 类型:
templatestruct generator { struct promise_type { T value; generator get_return_object() { return generator{std::coroutine_handle::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; 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 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++协程编程与自定义协程实现的详细内容,更多请关注创想鸟其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1483256.html
微信扫一扫
支付宝扫一扫