c++20协程需显式编译标志且无标准异步文件i/o支持,必须手动封装非阻塞系统调用并实现awaitable接口,跨平台需按os分支处理,核心难点在于i/o状态机与协程生命周期的精确对齐。

协程支持需要C++20且编译器得开开关
不是所有编译器默认启用协程,clang++ 和 g++ 都必须显式加标志:-std=c++20 + -fcoroutines(GCC 12+)或 -stdlib=libc++ + -Xclang -enable-experimental-coroutines(Clang)。MSVC 默认支持但需 /std:c++20 /await。漏掉任一标志,co_await 会直接报错 use of undeclared identifier 'co_await' 或 no matching function for operator co_await。
另外,标准库没提供异步文件 I/O 的协程适配器,std::filesystem 和 std::fstream 全是同步阻塞的——不能直接 co_await 文件操作。
得自己封装非阻塞文件句柄 + epoll/kqueue/IOCP
Linux 下最轻量的是用 open() 配合 O_NONBLOCK | O_DIRECT,再扔进 epoll 等待可读/可写事件;Windows 得走 CreateFile + OVERLAPPED + GetQueuedCompletionStatus。macOS 用 kqueue。跨平台?先别想,硬切平台分支更稳。
-
read()和write()系统调用在非阻塞模式下返回-1且errno == EAGAIN或EWOULDBLOCK时,说明要等 I/O 就绪——这时才该挂起协程 - 每个文件描述符得绑定一个
epoll_event或OVERLAPPED对象,否则co_await没法知道“等谁” - 别用
std::thread去包同步读写再co_await线程结果——这根本不是异步,只是把阻塞挪到另一线程,还多一次线程切换开销
awaitable 类型必须实现 await_ready/await_suspend/await_resume
比如封装一次非阻塞 read,得写个 read_awaitable 类:
struct read_awaitable {
int fd;
void* buf;
size_t len;
ssize_t result = 0;
<pre class="brush:php;toolbar:false;">bool await_ready() const { return false; } // 总是挂起,交给 epoll 判定就绪
void await_suspend(std::coroutine_handle h) {
// 注册 fd 到 epoll,就绪后调用 h.resume()
register_epoll_read(fd, [h](int) { h.resume(); });
}
ssize_t await_resume() { return result; }};
注意:await_suspend 里不能直接调用 read()——那又变同步了;也不能在 resume 后才去读,得确保 await_resume() 返回前数据已填入 buf。常见错误是忘了在 epoll 回调里真正执行 read(),导致 await_resume() 返回 0 或脏数据。
async_file 类接口设计要避开 std::fstream 的坑
std::fstream 内部维护缓冲区、格式化状态、locale,全是同步语义,无法安全跨协程重入。所以 async_file 应只暴露裸字节操作:
- 构造时只接受
int fd或路径(内部调用openat()),不接管生命周期——用户负责close() - 成员函数全返回
task<ssize_t></ssize_t>(需自定义或用std::experimental::coroutine的task),例如task<ssize_t> read(void*, size_t)</ssize_t> - 不提供
operator 或 <code>getline()——那些属于上层解析逻辑,协程类只管 I/O 调度 - 如果要用
O_DIRECT,buffer 地址和长度必须页对齐(posix_memalign()),否则read()直接失败返回-1、errno == EINVAL
实际最难的不是写协程语法,而是把系统级非阻塞 I/O 的状态机和协程生命周期对齐:epoll 可能比协程早注册、晚触发,OVERLAPPED 结构体生命周期必须覆盖整个等待过程——这些细节一错,就会静默丢数据或死锁。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











