协程是 C++20 为了实现异步编程而引入的一种强大工具。它们通过把函数挂起(suspend)与恢复(resume)的过程抽象化,让开发者能够像写同步代码一样书写异步逻辑,显著提升代码可读性与维护性。本文将从协程的底层原理、关键类型及其使用方式,结合实例说明如何在实际项目中应用协程。
1. 协程的基本概念
1.1 协程的生命周期
协程的执行分为三段:初始化、挂起与恢复。C++ 协程的入口函数(co_await、co_yield、co_return)会在第一次调用时创建一个 coroutine handle,并在函数体中出现挂起点时返回。随后通过 handle.resume() 可以继续执行,直到下一个挂起点或函数结束。
1.2 协程的生成器
协程通过 `std::generator
` 或自定义 Promise/Handle 组合实现生成器模式。生成器允许消费者一次获取一个值,内部状态在协程挂起后保持,直到下次恢复。 ## 2. 关键类型 | 类型 | 作用 | 典型用法 | |——|——|———-| | `std::coroutine_handle` | 对协程的句柄,用于挂起/恢复 | `handle.resume()` | | `std::suspend_always` / `std::suspend_never` | 决定是否挂起 | 在协程定义中使用 | | `std::promise_type` | 协程的 promise,定义返回值和错误处理 | 通过 `co_return` 触发 | ## 3. 实战:异步文件读取 下面演示一个简易的异步文件读取器,使用协程实现非阻塞 I/O。 “`cpp #include #include #include #include #include #include struct FileReadResult { std::string data; bool eof = false; }; struct FileReadPromise { FileReadResult result; std::suspend_always yield_value(const std::string& chunk) { result.data += chunk; return {}; } std::suspend_always initial_suspend() { return {}; } std::suspend_always final_suspend() noexcept { return {}; } void return_void() {} FileReadResult get_return_object() { return result; } }; struct AsyncFileReader { struct promise_type : FileReadPromise { AsyncFileReader get_return_object() { return AsyncFileReader{std::coroutine_handle ::from_promise(*this)}; } }; std::coroutine_handle handle; explicit AsyncFileReader(std::coroutine_handle h) : handle(h) {} ~AsyncFileReader() { if (handle) handle.destroy(); } FileReadResult operator()() { handle.resume(); return handle.promise().result; } }; AsyncFileReader readFileAsync(const std::string& path) { std::ifstream fin(path, std::ios::binary); if (!fin) co_return; std::string buffer(1024, ‘\0’); while (fin.read(buffer.data(), buffer.size())) { co_yield buffer; std::this_thread::sleep_for(std::chrono::milliseconds(10)); // 模拟异步等待 } co_yield buffer.substr(0, fin.gcount()); // 最后一次读 } int main() { auto reader = readFileAsync(“sample.txt”); while (true) { auto res = reader(); if (res.data.empty()) break; std::cout