C++ Boost.Asio 入门 之 多任务
C++ Boost.Asio 入门 之 多任务
上一节我们使用下面的代码完成了Hello World.这是完全异步的代码.
static awaitable<std::string> async_print(const std::string message){
std::cout << "message1: " << message << "\n";
auto executor = co_await boost::asio::this_coro::executor;
std::cout << "message2: " << message << "\n";
boost::asio::steady_timer timer(executor);
timer.expires_after(std::chrono::seconds(1));
std::cout << "message3: " << message << "\n";
co_await timer.async_wait(boost::asio::use_awaitable);
std::cout << "message4: " << message << "\n";
co_return "Hello World Coroutine!";
}
void learn04(){
boost::asio::io_context ioContext(1);
auto result = boost::asio::co_spawn(ioContext, async_print("Hello World From Coroutine!"), boost::asio::use_future);
ioContext.run();
std::cout << result.get() << "\n";
}
执行下面代码体验1个线程执行多个协程的效率
static boost::asio::awaitable<std::string> async_print(const std::string message){
std::cout << "message1: " << message << "\n";
auto executor = co_await boost::asio::this_coro::executor;
std::cout << "message2: " << message << "\n";
boost::asio::steady_timer timer(executor);
timer.expires_after(std::chrono::seconds(1));
std::cout << "message3: " << message << "\n";
co_await timer.async_wait(boost::asio::use_awaitable);
std::cout << "message4: " << message << "\n";
const auto threadId = std::this_thread::get_id();
std::cout << "threadId: " << threadId << "\n";
co_return "Hello World Coroutine!";
}
void learn02(){
std::cout << "hello World02n\n";
boost::asio::io_context ioContext(1);
std::vector<std::future<std::string>> results;
constexpr u_int N = 10000;
for(u_int i = 0; i < N; i ++ ){
results.emplace_back(boost::asio::co_spawn(ioContext, async_print("Hello World From Coroutine!"), boost::asio::use_future));
}
ioContext.run();
for(u_int i = 0; i < N; i ++ ){
std::cout << "result i: " << i << ", value: " << results[i].get() << "\n";
}
}
本节我们来看下如何使用Boost.Asio来进行多任务编程。
线程池 + 协程
static awaitable<int> async_print(const int a, const int b){
auto threadId = std::this_thread::get_id();
std::cout << "threadId: " << threadId << "\n";
co_return a + b;
}
static constexpr u_int N = 100;
void learn04(){
auto cores = std::thread::hardware_concurrency();
std::cout << "cores: " << cores << "\n";
boost::asio::io_context ioContext;
// 创建一个 work_guard 避免 io_context 过早退出
auto work = boost::asio::make_work_guard(ioContext);
// 启动线程池
std::vector<std::thread> threads;
for(unsigned i = 0; i < cores; ++i){
threads.emplace_back([&](){ ioContext.run(); });
}
// 提交协程
auto result1 = boost::asio::co_spawn(ioContext, async_print(1, 2), boost::asio::use_future);
auto result2 = boost::asio::co_spawn(ioContext, async_print(3, 4), boost::asio::use_future);
// 等待结果
std::cout << result1.get() << "\n";
std::cout << result2.get() << "\n";
// 停止 io_context
work.reset();
for(auto& t : threads) t.join();
}
实现一个awaitable
// 用 asio::post 包装任意耗时操作
boost::asio::awaitable<int> my_async_task(int value) {
auto exec = co_await boost::asio::this_coro::executor;
// post 一个任务到 io_context
co_await boost::asio::post(exec, boost::asio::use_awaitable);
auto threadId = std::this_thread::get_id();
// std::this_thread::sleep_for(std::chrono::microseconds(100));
std::cout << "running in io_context thread threadId: " << threadId << "\n";
std::this_thread::sleep_for(std::chrono::microseconds(100));
co_return value * 2;
}
static awaitable<int> asyncReadFile(const std::string fileName){
std::this_thread::sleep_for(std::chrono::microseconds(200));
int result = co_await my_async_task(42); // 自定义 Awaitable
std::this_thread::sleep_for(std::chrono::microseconds(200));
std::cout << "after co_await, result=" << result << "\n";
std::this_thread::sleep_for(std::chrono::microseconds(200));
co_return 1 + 2;
}
static constexpr u_int N = 10000;
void learn04(){
auto cores = std::thread::hardware_concurrency();
std::cout << "cores: " << cores << "\n";
boost::asio::io_context ioContext;
// 创建一个 work_guard 避免 io_context 过早退出
auto work = boost::asio::make_work_guard(ioContext);
// 启动线程池
std::vector<std::thread> threads;
for(unsigned i = 0; i < cores; ++i){
threads.emplace_back([&](){ ioContext.run(); });
}
// 提交协程
auto result1 = boost::asio::co_spawn(ioContext, asyncReadFile("D:/SoftWare/LanguageProjects/C++Projects/learn01/src/learn02/learn02.cpp"), boost::asio::use_future);
std::this_thread::sleep_for(std::chrono::microseconds(100));
auto result2 = boost::asio::co_spawn(ioContext, asyncReadFile("D:/SoftWare/LanguageProjects/C++Projects/learn01/src/learn01/learn01.cpp"), boost::asio::use_future);
// 等待结果
std::cout << result1.get() << "\n";
std::this_thread::sleep_for(std::chrono::microseconds(100));
std::cout << result2.get() << "\n";
std::vector<std::future<int>> results;
for(int i = 0; i < N; i ++ ){
results.emplace_back(boost::asio::co_spawn(ioContext, asyncReadFile("D:/SoftWare/LanguageProjects/C++Projects/learn01/src/learn02/learn02.cpp"), boost::asio::use_future));
}
for(int i = 0; i < N; i ++ ){
std::cout << "result: " << i << ": " << results[i].get() << "\n";
}
// 停止 io_context
work.reset();
for(auto& t : threads) t.join();
}
TODO 下周末继续分析,协程 搭配
Boost.Asio还真是爽呀!!!
TODO
- 异步 vs 同步
- 网络请求,复用请求
- 使用协程 开启 web 服务器

C++ Boost.Asio 入门 之 多任务
浙公网安备 33010602011771号