协程(coroutine)在C++20中正式加入标准库,提供了对轻量级协作式并发的原生支持。相比传统的线程,协程具有更低的创建与切换成本,更直观的代码结构以及更好的可组合性。本文将从协程的基本概念、语法实现、典型使用场景以及未来发展趋势四个方面,系统阐述C++协程的技术细节和实践价值。
1. 协程的基本概念
协程是一种在多任务之间共享执行上下文的程序结构。它允许在运行时暂停(yield)或恢复(resume)函数的执行,而不需要将执行权完全交给调度器。协程的核心是 暂停点(suspend point)和 恢复点(resume point)。在C++20中,协程通过 co_await、co_yield、co_return 三个关键字实现协作式暂停与返回。
co_await:在等待一个 awaitable 对象时暂停协程。
co_yield:生成一个值并暂停协程,等待下一个调用。
co_return:终止协程并返回一个值。
协程的状态由 promise 对象管理,promise 保存协程的结果、异常信息以及对外部接口的访问。协程函数的返回类型是 std::future、std::generator 或自定义 `generator
`。
## 2. 协程的语法实现
下面给出一个最简的协程实现例子:计算斐波那契数列。
“`cpp
#include
#include
#include
template
struct Generator {
struct promise_type {
T current_value;
std::optional
value_;
std::exception_ptr exception_;
Generator get_return_object() {
return Generator{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;
value_ = value;
return {};
}
void return_void() {}
void unhandled_exception() { exception_ = std::current_exception(); }
};
std::coroutine_handle
coro;
explicit Generator(std::coroutine_handle
h) : coro(h) {}
~Generator() { if (coro) coro.destroy(); }
bool next() {
coro.resume();
return !coro.done();
}
T value() const { return coro.promise().current_value; }
};
Generator
fibonacci(int n) {
int a = 0, b = 1;
for (int i = 0; i
#include
asio::awaitable
async_echo(asio::ip::tcp::socket sock) {
char buffer[1024];
std::size_t n = co_await sock.async_read_some(asio::buffer(buffer), asio::use_awaitable);
co_await asio::async_write(sock, asio::buffer(buffer, n), asio::use_awaitable);
co_return;
}
“`
### 3.2 并行流水线
在 CPU 密集型或数据流处理时,可用协程实现流水线结构。每个阶段是一个协程,数据通过 `co_yield` 传递,避免显式的线程间通信。
### 3.3 生成器与迭代器
协程天然地实现了生成器模式,适用于需要按需生成大量数据的场景,例如大规模日志解析、图像处理等。
## 4. 与线程的对比
| 维度 | 线程 | 协程 |
|——|——|——|
| 创建成本 | 1-2 ms |