首页 > 后端开发 > C++ > 正文

c++中的协程是如何挂起和恢复的_c++ coroutine_handle详解【底层】

裘德小鎮的故事
发布: 2025-12-16 13:45:08
原创
462人浏览过
C++20协程的挂起与恢复由coroutine_handle显式控制,依赖awaitable对象的await_suspend()行为;resume()跳转至挂起点下一条指令,destroy()显式释放帧内存。

c++中的协程是如何挂起和恢复的_c++ coroutine_handle详解【底层】

在 C++20 中,协程的挂起与恢复并非由语言直接调度,而是通过用户定义的 coroutine_handle 显式控制——它本质是一个轻量级、可复制的指针包装器,指向协程帧(coroutine frame)的内存首地址。真正决定“何时挂起”“如何恢复”的,是协程函数体内 co_await 表达式所作用的 awaitable 对象的行为,而 coroutine_handle 是执行这些行为的唯一入口。

挂起:由 awaitable 的 await_suspend() 触发

当协程执行到 co_await expr 时,编译器会调用 expr.await_suspend(handle)(若存在)。这个函数的返回值决定了挂起后的行为:

  • 返回 void:协程立即挂起,控制权交还给调用者;后续必须手动调用 handle.resume() 才能继续
  • 返回 booltrue 表示已自行安排恢复(如投递到线程池),协程挂起且不自动恢复;false 表示未安排,协程立即恢复(即“不挂起”,相当于同步执行)
  • 返回另一个 coroutine_handle:协程挂起,并将控制权转移给该 handle(常用于链式协程或尾调用优化)

注意:挂起操作本身不释放协程帧内存,只是将协程状态设为 suspended,并保存当前上下文(寄存器、局部变量等)到帧中。

coroutine_handle 的构造与有效性

它不能直接构造,只能通过以下方式获得:

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

  • co_await 表达式中传入的参数(即 await_suspend 的形参)
  • promise_type::get_return_object_on_allocation_failure() 等 promise 回调中(需配合自定义分配器)
  • 从其他 handle 派生:handle.address() 得到原始指针,再用 from_address() 重建(仅当确定内存有效时)

调用 handle.done() 可判断是否已结束(初始/已恢复完毕/已销毁);handle.promise() 返回对 promise 对象的引用,用于读写协程状态;handle.address() 返回帧起始地址,可用于内存管理或调试。

达芬奇
达芬奇

达芬奇——你的AI创作大师

达芬奇 166
查看详情 达芬奇

恢复:resume() 的底层含义

handle.resume() 并非“唤醒线程”,而是跳转回协程上次挂起点的下一条指令(由编译器生成的恢复标签决定)。它要求:

  • handle 必须有效且指向一个已挂起(!done())但未被销毁的协程帧
  • 协程帧内存必须仍可访问(未被 operator delete 释放)
  • 恢复时不会重新进入 promise 构造或初始 suspend,而是从中断处继续执行

若在 resume 前已调用 destroy(),或帧内存被复用,行为是未定义的。因此,典型模式是:在 await_suspend 返回 void 后,由外部事件(IO 完成、定时器触发、另一线程通知)安全地调用 resume()

销毁协程帧:显式 vs 隐式

协程帧的生命周期独立于 handle:

  • handle.destroy():手动释放帧内存(调用 promise 的析构、operator delete),之后 handle 变为无效
  • 隐式销毁:当协程执行到末尾(或抛出未捕获异常),且处于 final_suspend 状态时,编译器会自动调用 destroy() —— 这正是为什么 final_suspend 的 awaitable 通常返回 std::suspend_always(挂起等待显式销毁)或自定义逻辑(如自动回收)

常见错误是 resume 后未及时 destroy,导致内存泄漏;或过早 destroy 后仍尝试 resume,引发崩溃。正确做法是:final_suspend 返回的 awaitable 应明确管理帧生命周期。

基本上就这些。协程没有运行时调度器,没有隐式上下文切换,一切挂起/恢复/销毁都经由 coroutine_handle 和 awaitable 协同完成——它不是语法糖,而是一套可预测、可调试、完全暴露给用户的协作式控制流原语。

以上就是c++++中的协程是如何挂起和恢复的_c++ coroutine_handle详解【底层】的详细内容,更多请关注php中文网其它相关文章!

c++速学教程(入门到精通)
c++速学教程(入门到精通)

c++怎么学习?c++怎么入门?c++在哪学?c++怎么学才快?不用担心,这里为大家提供了c++速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

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