如何将boost::asio::awaitable转换为std::future?
boost::asio::awaitable 转换为 std::future 的惯用实现
Boost.Asio 内置了对 std::future 的原生适配,最常用的实现方式是结合 co_spawn 调度接口与 boost::asio::use_future 完成令牌。
基础使用示例
首先定义返回boost::asio::awaitable的协程函数:
#include <boost/asio.hpp> #include <chrono> boost::asio::awaitable<int> async_calculate() { // 模拟异步等待操作 co_await boost::asio::steady_timer( co_await boost::asio::this_coro::executor, std::chrono::seconds(1) ).async_wait(boost::asio::use_awaitable); co_return 42; }
转换为std::future的调用逻辑:
#include <future> #include <iostream> #include <thread> int main() { boost::asio::io_context ioc; // 核心调用:co_spawn配合use_future返回std::future对象 std::future<int> result_fut = boost::asio::co_spawn( ioc.get_executor(), async_calculate(), boost::asio::use_future ); // 单独启动线程运行io_context,避免阻塞主线程的future等待 std::thread io_thread([&ioc] { ioc.run(); }); // 等待异步操作完成获取结果 std::cout << "异步计算结果:" << result_fut.get() << std::endl; io_thread.join(); return 0; }
注意事项
- 必须保证
io_context在std::future调用get()完成前保持运行状态,否则协程不会被调度,future会永久阻塞。 - 如果协程内部抛出未捕获异常,异常会被自动传递到
std::future中,调用get()时会重新抛出该异常。 - 该特性要求Boost版本 >= 1.70,旧版本可以手动封装promise实现相同逻辑,示例如下:
template<typename T> std::future<T> awaitable_to_future(boost::asio::awaitable<T> awaitable_obj, boost::asio::any_io_executor executor) { auto promise_ptr = std::make_shared<std::promise<T>>(); std::future<T> result_fut = promise_ptr->get_future(); boost::asio::co_spawn(executor, std::move(awaitable_obj), [promise_ptr](std::exception_ptr ex, T result) mutable { if (ex) { promise_ptr->set_exception(std::move(ex)); } else { promise_ptr->set_value(std::move(result)); } } ); return result_fut; }
内容的提问来源于stack exchange,提问作者Sogartar
相关产品推荐
相关产品推荐

