协程(coroutine)是C++20对异步编程的一大改进,它让我们可以在单线程环境下以同步的方式编写异步代码。下面我们通过一个小例子来演示如何在 C++20 中实现一个简易的异步 IO 操作,并说明其关键技术点。
1. 了解协程的基本概念
协程本质上是能够暂停和恢复执行的函数。C++20 对协程的支持主要通过以下几个关键类型完成:
std::suspend_always / std::suspend_never:决定协程在何时暂停。
std::coroutine_handle<>:协程句柄,负责管理协程生命周期。
std::future / std::promise:传统异步结果包装。
- 自定义的
promise_type:协程函数的返回类型与其内部状态管理。
2. 构建一个简单的协程包装
下面的代码示例演示了一个 async_io 函数,它返回一个 `std::future
`,内部使用协程模拟一个异步读操作。
“`cpp
#include
#include
#include
#include
struct async_io_task {
struct promise_type;
using handle_type = std::coroutine_handle
;
struct promise_type {
int result_;
async_io_task get_return_object() {
return async_io_task{handle_type::from_promise(*this)};
}
std::suspend_always initial_suspend() { return {}; }
std::suspend_always final_suspend() noexcept { return {}; }
void return_value(int v) { result_ = v; }
void unhandled_exception() { std::terminate(); }
};
handle_type coro_;
async_io_task(handle_type h) : coro_(h) {}
~async_io_task() { if (coro_) coro_.destroy(); }
std::future
get_future() {
struct Awaiter {
handle_type coro_;
bool await_ready() const noexcept { return false; }
void await_suspend(std::coroutine_handle awaiting) noexcept {
std::thread([coro = coro_, awaiting]() {
coro.resume(); // 让协程真正运行
awaiting.resume(); // 继续等待者
}).detach();
}
int await_resume() const noexcept { return coro_.promise().result_; }
};
return std::async(std::launch::async, [a = Awaiter{coro_}]() mutable {
return a.await_resume();
});
}
};
async_io_task async_io() {
std::cout fut = task.get_future(); // 获取 std::future
std::cout