C++20协程的执行流程

By pocaster

协程是一种特殊的函数,可以在函数执行过程中暂停和恢复。协程可以用于实现异步编程,特别是在Unity中,协程可以用于实现动画、移动、等待等操作。

用 Mermaid 绘制一个协程的执行流程图,以 say_hello 协程为例:

sequenceDiagram participant Main as 主线程 participant Task as Task对象 participant Promise as 允诺对象 participant Coroutine as 协程函数体 participant Async as 异步任务 Main->>Task: 创建协程(say_hello) Note over Task: 1. 创建允诺对象
2. 创建协程句柄 Task->>Promise: initial_suspend() Promise-->>Task: 挂起 Main->>Task: resume() Task->>Coroutine: 开始执行 Note over Coroutine: 输出"Starting [name]" Coroutine->>Async: 创建异步任务 Async->>Async: 执行睡眠 loop 等待异步任务完成 Coroutine->>Coroutine: co_await suspend_always Coroutine-->>Task: 挂起 Task->>Main: 返回控制权 Main->>Task: resume() Task->>Coroutine: 恢复执行 Coroutine->>Async: 检查是否完成 end Async-->>Coroutine: 任务完成 Coroutine->>Coroutine: 输出"Hello [name]" Coroutine->>Promise: co_return Promise->>Promise: final_suspend() Promise-->>Task: 标记完成 Task->>Main: 协程结束
  1. 创建阶段
    • 主线程创建协程
    • 创建允诺对象和协程句柄
    • 初始挂起
  2. 执行阶段
    • 协程开始执行
    • 创建异步任务
    • 在等待期间反复挂起和恢复
  3. 完成阶段
    • 异步任务完成
    • 输出完成信息
    • 最终挂起
    • 标记协程完成

这个流程展示了协程如何:

  • 在需要等待时挂起
  • 让出控制权给主线程
  • 在适当的时候恢复执行
  • 最终完成并清理资源

这就是为什么协程可以高效地处理异步操作 - 它不会阻塞线程,而是在等待时让出控制权,让其他任务可以执行。

gantt title 协程和线程配合执行时间线 dateFormat HH:mm:ss section 主线程 创建协程 :00:00:00, 1s 创建其他协程 :00:00:01, 2s 等待完成 :00:00:03, 2s section Alice协程 初始挂起 :00:00:00, 1s 输出开始 :00:00:01, 1s 等待循环 :00:00:02, 2s 输出完成 :00:00:04, 1s section Alice异步线程 开始睡眠 :00:00:01, 2s 完成睡眠 :00:00:03, 1s
gantt title 三个协程的线程执行时间线 dateFormat HH:mm:ss section 主线程 创建协程 :00:00:00, 1s 等待完成 :00:00:01, 3s section Alice协程 (2秒) 创建线程1 :00:00:00, 1s 线程1睡眠 :00:00:01, 2s 完成 :00:00:03, 1s section Bob协程 (1秒) 创建线程2 :00:00:00, 1s 线程2睡眠 :00:00:01, 1s 完成 :00:00:02, 1s section Charlie协程 (3秒) 创建线程3 :00:00:00, 1s 线程3睡眠 :00:00:01, 3s 完成 :00:00:04, 1s
sequenceDiagram participant Main as 主线程 participant Task as 协程 Main->>Task: 创建协程 Note over Task: 初始状态:暂停 Main->>Task: wait_for_all开始 Main->>Task: resume() 第一次 Note over Task: 执行到co_await挂起点 loop 等待循环 Main->>Task: 检查是否完成 alt 未完成 Main->>Task: resume() 再次尝试 else 完成 Main->>Main: 退出循环 end end
Tags: Tech Public