C++如何实现简单的C++协程任务调度器(Coroutines)

阿强姑娘_5083

阿强姑娘_5083

2026-06-10

628人浏览

原创

协程任务调度器核心是std::coroutine_handle与手动状态管理,需自实现调度逻辑;最简结构为可运行队列加驱动循环,协程创建即入队,resume后须立即检查done()并销毁已完成handle。

c++如何实现简单的c++协程任务调度器(coroutines)

协程任务调度器的核心是 std::coroutine_handle 和手动状态管理

标准 C++20 协程本身不提供调度器,co_await 只负责挂起/恢复,调度逻辑必须自己写。关键不是“怎么启动协程”,而是“谁来决定哪个协程该恢复、何时恢复”。最简调度器只需一个可运行任务队列 + 一个驱动循环,所有协程都以 std::coroutine_handle 形式入队。

常见错误是试图在 await_suspend 里直接调用 resume() —— 这会同步执行,失去调度意义;正确做法是把 handle 存起来,由调度器统一轮询或事件触发后恢复。

  • std::coroutine_handle 必须在 resume 前保持有效:不能是栈上临时对象、不能已 destroy
  • 不要用裸指针存 handle,推荐 std::vector<:coroutine_handle>> </:coroutine_handle> 或 std::queue(注意 std::queue 不支持 move-only 类型,得用 std::deque)
  • 调度器自身不能是协程,它必须是普通函数(比如 run()),否则无法启动第一个协程

如何让协程自动进入调度器队列(promise_type::get_return_object() 是入口)

每个协程函数返回一个自定义类型(如 Task),它的 promise_type 控制协程生命周期。关键是在 get_return_object() 中创建 handle 并立即入队——这样协程一创建就“就绪”,而不是等你手动 resume。

示例片段:

struct Task {
  struct promise_type {
    Task get_return_object() { 
      return Task{std::coroutine_handle<promise_type>::from_promise(*this)}; 
    }
    std::suspend_never initial_suspend() { return {}; }
    std::suspend_always final_suspend() noexcept { return {}; }
    void unhandled_exception() { std::terminate(); }
    void return_void() {}
  };
  std::coroutine_handle<promise_type> handle;
  Task(std::coroutine_handle<promise_type> h) : handle(h) {}
  ~Task() { if (handle) handle.destroy(); }
};
</promise_type></promise_type></promise_type>

注意:initial_suspend() 返回 std::suspend_never 才能让协程创建后立刻进入调度队列;若返回 std::suspend_always,它会挂起,你得手动 resume 一次才能入队——这违背“自动调度”初衷。

C++14
C++14

C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。

下载

调度器 run() 循环中 resume 的安全边界在哪

每次 resume() 后必须立刻检查协程是否已完成(handle.done()),否则可能对已销毁的 handle 调用 resume,引发未定义行为。完成的协程 handle 应立即 destroy,不能留着。

  • resume 前不必检查 done(),但 resume 后必须检查
  • 不能在 await_suspend 中 resume 当前 handle(会导致栈溢出),这是死循环陷阱
  • 如果协程在 final_suspend 挂起,done() 返回 true,此时应 destroy handle,不能再 resume
  • 简单调度器可采用“运行到空”策略:while (!ready_queue.empty()) { auto h = pop(); h.resume(); if (h.done()) h.destroy(); }

为什么不用 std::jthread 或线程池封装调度器

协程调度器本身不等于多线程——它可以完全单线程运行(比如游戏主循环、嵌入式事件循环)。加线程反而引入竞态:多个线程往同一队列 push/pop std::coroutine_handle 需要锁,而 handle 是 move-only、不可复制,锁粒度难控制。

真正需要并发调度时,更稳妥的做法是分层:单个调度器绑定一个线程,多个调度器实例各自独立运行;跨调度器通信走 channel 或原子队列。强行用 std::jthread 包裹 run() 并不解决本质问题,还掩盖了协程与线程的职责分离。

最容易被忽略的一点:协程的栈空间由编译器分配在 caller 栈帧上(默认 stackful 协程不存在),所以调度器切换协程不涉及栈拷贝,但这也意味着不能跨线程 resume 同一个 handle——除非你用 boost::context 或平台 API 自行管理栈内存。

C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

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

下载

相关标签:

c++

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
c++和c语言的区别有哪些
c++和c语言的区别有哪些

c++和c语言的区别:1、面向对象编程(OOP)支持不同;2、新增特性不同;3、标准库不同;4、编译方式不同;5、命名空间不同等等。想了解更多c++的相关内容,可以阅读本专题下面的文章。

2024.03.14

2248

9

c++和python学习顺序推荐
c++和python学习顺序推荐

一般建议先学习C++,再学习Python,因为这样可以逐步从较为底层的编程语言向更高级的语言过渡。想了解更多python的相关内容,可以阅读本专题下面的文章。

2024.03.14

1019

6

python和c++学习性价比分析
python和c++学习性价比分析

Python易于学习,广泛应用于Web开发、数据科学和人工智能等领域,但性能较低。C语言性能高,适用于对性能要求较高的场景,如游戏开发和系统编程,但学习曲线陡峭,错误处理复杂。想了解更多python的相关内容,可以阅读本专题下面的文章。

2024.03.14

447

5

c语言和c++一样吗
c语言和c++一样吗

c语言和c++是两种不同的编程语言,虽然有相似之处,但存在显著差异。c语言专注于过程式编程和系统级开发,以简洁、高效著称。c++作为c语言的超集,引入了面向对象编程,增强了代码组织和管理能力,但学习曲线也更陡峭。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.03.14

327

5

c语言和c++先学哪个好
c语言和c++先学哪个好

初学者选择学习c语言还是c++语言,需要根据个人学习目标、背景以及编程兴趣和预期应用方向来决定。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.03.14

406

5

c语言和c++的区别和联系
c语言和c++的区别和联系

c语言和c++是计算机科学领域应用广泛的编程语言。虽然它们有着相似的基础,但它们在语言类型、语法功能和内存管理方面存在着显著差异。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.03.14

580

5

c++软件中文更改教程
c++软件中文更改教程

对于 ide,可通过打开设置,找到语言设置,选择中文,并保存更改。对于非 ide 应用程序,可查找设置或选项,选择语言设置,更改为中文,并保存更改。想了解更多c++的相关内容,可以阅读本专题下面的文章。

2024.03.21

1409

9

python和java和c++学习性价比分析
python和java和c++学习性价比分析

Python以其易学性、丰富的库和活跃的社区而著称,适合数据科学、人工智能和Web开发。Java以其跨平台性、企业级应用开发和Android应用开发而闻名。C++以其底层控制能力、高效性能和游戏开发而著称。选择哪种语言取决于个人兴趣、职业方向和特定需求。想了解更多python和java和c++的相关内容,可以阅读本专题下面的文章。

2024.03.22

1217

7

c++和c语言学习顺序推荐
c++和c语言学习顺序推荐

对于初学者,建议先学习C语言,掌握编程基础后再转入C++,便于理解面向对象编程概念。有编程经验者可直接学习C++,快速接触高级编程技术。想了解更多c++和c语言的相关内容,可以阅读本专题下面的文章。

2024.03.25

1325

9

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++ Core Guidelines
C++ Core Guidelines

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

C++ 官方标准说明
C++ 官方标准说明

共0课时 | 0人学习