从 generator 到 async_generator:协程生成器的三层进化
从 generator 到 async_generator:协程生成器的三层进化 本专栏文章:拆开 cppcoro 给你看 · 第 4 篇 前几篇一直在讲"等一个结果返回"的协程模式——task<T>、同步原语、when_all。但协程还有另一面:用协程产生一系列值,而不是一次返回一个结果。 cppcoro 为此提供了三种生成器,每一种都是为解决前一种的瓶颈而生的。本文从一个具体痛点出发:遍历一棵二叉树的所有节点,看着普通的 generator 怎么在递归场景下性能退化成 O(N²),然后 recursive_generator 怎么用 O(1) 的 pull() 解决,最后 async_generator 怎么让生成器支持 co_await。 1 2 3 generator<T> → O(1) 遍历平面序列,但递归时 operator++() 退化成 O(depth) recursive_generator<T> → pull() 直接驱动叶子,递归场景 O(1) async_generator<T> → 支持 co_await,值可以异步产生 1. generator<T> —— 同步惰性序列 1.1 最简单的使用场景 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 generator<int> fibonacci() { int a = 0, b = 1; for (int i = 0; i < 10; ++i) { co_yield b; int t = a; a = b; b += t; } } int main() { for (int n : fibonacci()) { std::cout << n << " "; // 1 1 2 3 5 8 13 21 34 55 } } 1.2 和 task<T> 的设计对比 特性 task<T> generator<T> 用途 产生一个最终结果 产生一系列中间值 关键字 co_return co_yield 可以用 co_await? ✅ ❌ final_suspend FinalAwaiter(转移控制权) suspend_always 谁决定何时结束 协程自己 (co_return) 调用者 (不再调用 ++it) 1.3 为什么 final_suspend 是 suspend_always? 与 task<T> 的 FinalAwaiter(把控制权转回等待者)不同,generator 的 final_suspend 就是纯纯的 suspend_always。 ...