C++20引入的协程(Coroutines)为异步编程提供了一种更直观、更高效的语法结构。与传统的回调或线程方式相比,协程能够让代码保持同步的写法,却在执行时能够挂起并恢复,从而实现高性能的异步操作。本文将系统讲解协程的核心概念、实现细节以及在实际项目中的应用示例。
1. 协程的基本概念
协程是一种“可挂起的函数”,它可以在执行过程中暂停(co_await、co_yield 或 co_return),并在之后某个时刻恢复。C++20标准将协程的实现分为三大角色:
| 角色 | 作用 | 关键词 |
|---|---|---|
| 协程函数 | 定义协程的入口点 | co_await、co_yield、co_return |
| 协程返回类型 | 决定协程的状态机 | std::future、std::generator、自定义类型 |
| 协程框架 | 生成协程状态机 | std::suspend_always、std::suspend_never、std::promise |
协程的执行模型类似于生成器,但它更通用、更强大。C++的协程本质上是由编译器在编译阶段生成一个状态机类,所有挂起点会被编译成分支,协程内部的变量则变成状态机的成员。
2. 基本语法
// 简单的协程函数,返回 std::generator <int>
std::generator <int> count_to(int n) {
for (int i = 0; i < n; ++i) {
co_yield i; // 挂起并返回当前值
}
}
调用方式:
for (int value : count_to(5)) {
std::cout << value << ' '; // 输出 0 1 2 3 4
}
协程也可以返回 `std::future
` 或者 `std::promise`,用于异步计算: “`cpp std::future async_add(int a, int b) { co_return a + b; // 立即返回结果 } “` ### 3. 协程与异步 IO 在网络编程或文件 IO 中,协程可以大大简化代码。假设我们使用 Boost.Asio 的异步接口: “`cpp asio::awaitable handle_client(tcp::socket socket) { char data[1024]; std::size_t n = co_await socket.async_read_some(asio::buffer(data), asio::use_awaitable); std::cout class simple_generator { public: struct promise_type { T current_value; simple_generator get_return_object() { return simple_generator{Handle{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 value) { current_value = value; return {}; } void return_void() {} void unhandled_exception() { std::terminate(); } }; using Handle = std::coroutine_handle ; simple_generator(Handle h) : coro(h) {} ~simple_generator() { if (coro) coro.destroy(); } T operator*() const { return coro.promise().current_value; } bool next() { if (!coro.done()) coro.resume(); return !coro.done(); } private: Handle coro; }; “` 使用方式与 `std::generator` 类似: “`cpp simple_generator seq(int n) { for (int i = 0; i