C++20标准中的协程:从概念到实践

协程(coroutine)是C++20新加入的特性,它为实现轻量级的异步和生成器提供了统一的语法与运行时支持。与传统的回调或线程相比,协程能够在单个线程中暂停与恢复执行,避免了堆栈复制、锁竞争以及回调地狱等问题。本文将介绍协程的基本概念、关键类型以及一个完整的实现示例,帮助读者快速上手并将协程融入日常开发。

1. 协程的核心概念

1.1 生成器(Generator)

生成器是一种特殊的协程,能够按需返回一系列值。标准库提供了 `std::generator

`,但目前实现并不统一。一般实现思路是: “`cpp std::generator count(int n) { for (int i = 0; i ` 管理执行上下文。`Promise` 类型定义了协程的生命周期行为,包括: – `initial_suspend()`:协程入口处是否立即挂起 – `final_suspend()`:协程退出时是否挂起 – `get_return_object()`:返回给调用者的对象 – `return_value()` / `unhandled_exception()`:返回值与异常处理 ### 1.3 协程操作符 – `co_return`:结束协程并返回值 – `co_yield`:产生值并挂起协程 – `co_await`:等待另一个可等待对象(如 `std::future`、`std::chrono::duration` 等) ## 2. 协程的实现细节 下面以一个简单的异步任务为例,演示协程的完整实现。我们实现一个 `async_sleep` 函数,用于异步等待指定毫秒数,然后返回一个字符串。 “`cpp #include #include #include #include #include struct sleep_awaiter { std::chrono::milliseconds ms; std::coroutine_handle handle; bool await_ready() const noexcept { return false; } void await_suspend(std::coroutine_handle h) { handle = h; std::thread([ms = ms, h]{ std::this_thread::sleep_for(ms); h.resume(); }).detach(); } void await_resume() const noexcept {} }; auto async_sleep(std::chrono::milliseconds ms) -> std::future { struct promise_type { std::promise prom; auto get_return_object() { return prom.get_future(); } std::suspend_never initial_suspend() { return {}; } std::suspend_never final_suspend() noexcept { return {}; } void return_value(std::string val) { prom.set_value(std::move(val)); } void unhandled_exception() { prom.set_exception(std::current_exception()); } }; struct awaitable { std::coroutine_handle h; awaitable(std::coroutine_handle h) : h(h) {} bool await_ready() const noexcept { return false; } void await_suspend(std::coroutine_handle awaiting) { h.promise().prom.set_exception(std::make_exception_ptr(std::runtime_error(“not used”))); awaiting.resume(); } void await_resume() const noexcept {} }; struct coroutine { std::coroutine_handle h; coroutine(promise_type& p) : h(std::coroutine_handle ::from_promise(p)) {} std::future get_future() { return h.promise().prom.get_future(); } }; struct start { std::chrono::milliseconds ms; start(std::chrono::milliseconds ms) : ms(ms) {} auto operator co_await() { struct awaiter { std::chrono::milliseconds ms; awaiter(std::chrono::milliseconds ms) : ms(ms) {} bool await_ready() const noexcept { return false; } void await_suspend(std::coroutine_handle h) { std::thread([ms, h]{ std::this_thread::sleep_for(ms); h.resume(); }).detach(); } void await_resume() const noexcept {} }; return awaiter(ms); } }; struct task { struct promise_type; using handle_type = std::coroutine_handle ; handle_type coro; task(handle_type h) : coro(h) {} ~task() { if (coro) coro.destroy(); } std::future get_future() { return coro.promise().prom.get_future(); } }; struct promise_type { std::promise prom; auto get_return_object() { return task{std::coroutine_handle ::from_promise(*this)}; } std::suspend_never initial_suspend() { return {}; } std::suspend_never final_suspend() noexcept { return {}; } void return_value(std::string val) { prom.set_value(std::move(val)); } void unhandled_exception() { prom.set_exception(std::current_exception()); } }; // coroutine body task coro = [&]()->task { co_await start(ms); co_return “Sleep done”; }(); return coro.get_future(); } “` 上述代码演示了: 1. **自定义 Awaiter**:实现了 `await_ready`、`await_suspend`、`await_resume` 三个成员,控制协程挂起与恢复。 2. **Promise 结构**:管理协程的返回值与异常,最终返回一个 `std::future` 给调用者。 3. **协程入口**:使用 `co_await` 等待 `sleep_awaiter` 的完成,然后 `co_return` 返回字符串。 使用示例: “`cpp int main() { auto fut = async_sleep(std::chrono::milliseconds(2000)); std::cout

发表评论