在C++20中,协程(Coroutines)为异步编程提供了原生语法支持。下面给出一个完整示例,演示如何使用std::experimental::generator(在C++20的实验特性中)读取文件内容,并利用协程实现非阻塞的异步文件读取。
核心思路
- 异步读取任务:定义一个返回
std::future的函数,内部使用协程读取文件。 - 协程生成器:利用
std::experimental::generator<std::string>逐行产生文件内容。 - 主线程:启动异步任务,随后继续执行其他业务逻辑,最终等待结果。
代码示例
#include <iostream>
#include <fstream>
#include <string>
#include <future>
#include <experimental/coroutine>
// 1. 生成器类型,逐行返回文件内容
template<typename T>
using generator = std::experimental::generator <T>;
// 2. 协程生成器实现
generator<std::string> read_file_lines(const std::string& path) {
std::ifstream fin(path);
if (!fin) {
co_yield "ERROR: Cannot open file.";
co_return;
}
std::string line;
while (std::getline(fin, line)) {
co_yield line; // 生成下一行
}
}
// 3. 异步读取函数,返回 std::future<std::vector<std::string>>
std::future<std::vector<std::string>> async_read_file(const std::string& path) {
return std::async(std::launch::async, [path] {
std::vector<std::string> result;
for (auto&& line : read_file_lines(path)) {
if (line.rfind("ERROR", 0) == 0) { // 错误行
result.push_back(line);
break;
}
result.push_back(line);
}
return result;
});
}
// 4. 主程序演示
int main() {
const std::string file_path = "sample.txt";
// 启动异步读取
std::future<std::vector<std::string>> future = async_read_file(file_path);
// 主线程可以做其他事情
std::cout << "正在进行其他工作...\n";
std::this_thread::sleep_for(std::chrono::seconds(1));
std::cout << "其他工作完成。\n";
// 等待读取结果
std::vector<std::string> lines = future.get();
std::cout << "读取到的文件内容:\n";
for (const auto& l : lines) {
std::cout << l << '\n';
}
return 0;
}
实现细节说明
read_file_lines使用co_yield逐行产生文件内容,若文件无法打开则直接返回错误信息。async_read_file调用std::async以后台线程启动协程,返回std::future,可以在主线程中非阻塞地等待结果。- 主线程在等待文件读取完成期间可执行其他任务,真正体现了异步协程的优势。
编译指令
g++ -std=c++20 -pthread -lstdc++experimental -o async_read async_read.cpp
注意:
-lstdc++experimental用于链接实验性协程支持库,若使用 Clang,请相应改为-stdlib=libc++。
扩展思路
- 错误处理:在协程内部使用异常或
std::optional进一步细化错误信息。 - 大文件优化:改用缓冲读取(如
std::ifstream::read),避免一次性将整个文件读入内存。 - 跨平台异步:结合
asio或boost::asio,实现真正意义上的非阻塞 I/O。
通过以上示例,你可以看到 C++20 的协程不仅语法优雅,而且能轻松实现高并发、异步的文件 I/O。希望对你后续的异步编程实践有所帮助。