C++20 的协程(co_await、co_yield、co_return)为异步编程提供了更直观的语法。下面通过一个简单的示例,演示如何利用协程来实现一个异步任务调度器。
1. 协程类型概览
- promise_type:协程的承诺对象,负责管理协程的生命周期。
- handle_type:协程句柄,用于控制协程(挂起、恢复、销毁)。
- awaiter:
co_await的等待对象,定义await_ready、await_suspend、await_resume三个方法。
2. 简单的异步函数
#include <coroutine>
#include <iostream>
#include <thread>
#include <chrono>
#include <optional>
struct AsyncResult {
struct promise_type {
std::optional <int> value_;
std::coroutine_handle <promise_type> caller_;
AsyncResult get_return_object() {
return AsyncResult{ std::coroutine_handle <promise_type>::from_promise(*this) };
}
std::suspend_always initial_suspend() { return {}; }
std::suspend_always final_suspend() noexcept {
if (caller_) caller_.resume();
return {};
}
void return_value(int v) { value_ = v; }
void unhandled_exception() { std::terminate(); }
};
std::coroutine_handle <promise_type> coro_;
AsyncResult(std::coroutine_handle <promise_type> h) : coro_(h) {}
~AsyncResult() { if (coro_) coro_.destroy(); }
};
struct AwaitableSleep {
std::chrono::milliseconds dur_;
AwaitableSleep(std::chrono::milliseconds d) : dur_(d) {}
bool await_ready() const noexcept { return false; }
void await_suspend(std::coroutine_handle<> h) {
std::thread([h, dur = dur_]() {
std::this_thread::sleep_for(dur);
h.resume();
}).detach();
}
void await_resume() const noexcept {}
};
AsyncResult async_task() {
std::cout << "Task started\n";
co_await AwaitableSleep{ std::chrono::seconds(2) };
std::cout << "Task resumed after sleep\n";
co_return 42;
}
int main() {
auto task = async_task();
// 模拟事件循环
while (true) {
if (!task.coro_.done()) {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
} else {
std::cout << "Result: " << task.coro_.promise().value_.value() << '\n';
break;
}
}
return 0;
}
3. 代码解析
AsyncResult包装协程句柄,提供了简洁的使用接口。AwaitableSleep是一个可等待对象,内部使用一个独立线程来实现非阻塞睡眠,睡眠结束后恢复协程。async_task展示了如何在协程内部co_await自定义等待对象,然后返回一个结果。main充当事件循环,持续检查协程是否完成。
4. 进一步扩展
- 任务调度:将
AwaitableSleep换成网络 I/O 或数据库查询的 awaitable。 - 错误处理:在
promise_type中实现unhandled_exception,将异常信息传递给外部。 - 多任务:使用 `std::vector ` 进行并行任务管理。
通过上述示例,你可以快速掌握 C++20 协程的基本使用模式,为构建高性能异步框架奠定基础。