You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Boost 1.66.0,如何从boost::asio::post获取future?

让Boost Asio的post返回future的方法

在Boost 1.66.0里,async_read这类异步操作能通过boost::asio::use_future返回future,是因为它们支持**完成令牌(Completion Token)**机制。而post本身是个“fire-and-forget”的函数,默认不返回future,但我们可以通过封装一个支持完成令牌的异步版本来实现相同效果。


核心思路:封装支持完成令牌的async_post

我们可以借助Boost Asio的async_initiate工具,把post包装成一个接受完成令牌的异步操作,这样就能直接用use_future作为令牌,让它返回future。

1. 无返回值的async_post

如果你只是想提交一个无返回值的任务,拿到future<void>来等待任务完成,用这个版本:

#include <boost/asio.hpp>
#include <future>

template <typename CompletionToken>
auto async_post(boost::asio::io_context& io_context, CompletionToken&& token)
{
    return boost::asio::async_initiate<CompletionToken, void()>(
        [&](auto&& completion_handler)
        {
            // 把完成处理程序提交到io_context
            boost::asio::post(io_context, std::forward<decltype(completion_handler)>(completion_handler));
        },
        token);
}

使用示例:

boost::asio::io_context io_ctx;

// 提交无返回值任务,拿到future<void>
auto fut = async_post(io_ctx, boost::asio::use_future);

// 运行io_context
std::thread t([&](){ io_ctx.run(); });

// 等待任务完成
fut.get();
t.join();

2. 带返回值的async_post

如果你的任务有返回值,希望future能拿到结果(或捕获任务抛出的异常),可以用这个增强版:

#include <boost/asio.hpp>
#include <future>
#include <type_traits>

template <typename Func, typename CompletionToken>
auto async_post(boost::asio::io_context& io_context, Func&& func, CompletionToken&& token)
{
    // 推导任务的返回类型
    using ResultType = decltype(std::declval<Func>()());

    return boost::asio::async_initiate<CompletionToken, void(ResultType)>(
        [&, func = std::forward<Func>(func)](auto&& completion_handler) mutable
        {
            boost::asio::post(io_context, [func = std::move(func), handler = std::forward<decltype(completion_handler)>(completion_handler)]() mutable
            {
                try
                {
                    if constexpr (std::is_void_v<ResultType>)
                    {
                        // 无返回值任务:执行后调用无参完成处理程序
                        func();
                        handler();
                    }
                    else
                    {
                        // 有返回值任务:把结果传递给完成处理程序
                        handler(func());
                    }
                }
                catch (...)
                {
                    // 将异常传递给完成处理程序,use_future会在get()时抛出该异常
                    std::rethrow_exception(std::current_exception());
                }
            });
        },
        token);
}

使用示例:

boost::asio::io_context io_ctx;

// 提交返回int的任务
auto fut = async_post(io_ctx, [](){ return 42; }, boost::asio::use_future);

io_ctx.run();

// 获取结果并输出42
std::cout << fut.get() << std::endl;

为什么这个方案可行?

boost::asio::async_initiate是Asio用来构建自定义异步操作的工具,它会根据你传入的完成令牌(比如use_future)自动生成对应的返回值(这里就是future)。当你用use_future作为令牌时,Asio会创建一个promise并返回其关联的future;完成处理程序被调用时,会自动设置promise的结果(或异常)。

这个封装完全遵循Asio的异步操作模型,和async_read使用use_future的逻辑完全一致。


内容的提问来源于stack exchange,提问作者Chris Hunt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:35:02