首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何从boost::asio::post中获得未来?

如何从boost::asio::post中获得未来?
EN

Stack Overflow用户
提问于 2018-04-20 22:55:35
回答 2查看 4.8K关注 0票数 8

我使用的是Boost 1.66.0,其中asio内置了对期货互操作的支持(而且已经有一段时间了)。我在网上看到的示例说明了如何在使用网络功能(如async_readasync_read_some等)时干净地实现这一点。这是通过提供boost::asio::use_future代替完成处理程序来实现的,这将导致启动函数按预期返回future

为了从boost::asio::post获得相同的行为,需要提供或包装函数的对象是什么?

我发布该工作的目的是在一个链的上下文中执行它,但在其他情况下等待工作完成,这样我就可以得到我想要做的行为:

代码语言:javascript
运行
复制
std::packaged_task<void()>  task( [] { std::cout << "Hello world\n"; } );
auto  f = task.get_future();
boost::asio::post(
    boost::asio::bind_executor(
        strand_, std::move( task ) ) );
f.wait();

但是根据boost::asio文档,boost::asio::post的返回类型与boost::asio::async_read这样的函数的返回类型相同,所以我觉得必须有一种更好的方法来避免中间packaged_task。与async_read不同的是,post没有“其他工作”可做,所以只提供boost::asio::use_future是没有意义的,但是我们可以定义一个async_result特性来获得相同的post行为。

是否有包装器或具有必要特征的东西来获得我想要的行为,还是我需要自己来定义它?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-11-17 16:09:34

@MartiNitro's idea with packaged_task已经成为库的一部分:现在您只需发布一个packaged_task,它将神奇地返回它的未来:

代码语言:javascript
运行
复制
    auto f = post(strand_, std::packaged_task<int()>(task));

现场演示

代码语言:javascript
运行
复制
#include <boost/asio.hpp>
#include <iostream>
#include <future>
using namespace std::chrono_literals;

int task() {
    std::this_thread::sleep_for(1s);
    std::cout << "Hello world\n";
    return 42;
}

int main() {
    boost::asio::thread_pool   ioc;
    auto strand_ = make_strand(ioc.get_executor());

    auto f = post(strand_, std::packaged_task<int()>(task));
    // optionally wait for future:
    f.wait();
    // otherwise .get() would block:
    std::cout << "Answer: " << f.get() << "\n";

    ioc.join();
}

打印

代码语言:javascript
运行
复制
Hello world
Answer: 42
票数 3
EN

Stack Overflow用户

发布于 2020-06-25 16:29:11

这是我想出来的,它本质上是将asio::post和插件封装在一个承诺/未来的对子中。我认为它也能适应你的需要。

代码语言:javascript
运行
复制
// outer scope setup
asio::io_context context;
asio::io_context::strand strand(context);


std::future<void> async_send(tcp::socket& socket, std::string message) {
    auto buffered = std::make_shared<std::string>(message);
    std::promise<void> promise;
    auto future = promise.get_future();

    // completion handler which only sets the promise.
    auto handler = [buffered, promise{std::move(promise)}](asio::error_code, std::size_t) mutable {
        promise.set_value();
    };

    // post async_write call to strand. Thas *should* protecte agains concurrent 
    // writes to the same socket from multiple threads
    asio::post(strand, [buffered, &socket, handler{std::move(handler)}]() mutable {
        asio::async_write(socket, asio::buffer(*buffered), asio::bind_executor(strand, std::move(handler)));
    });
    return future;
}

承诺可以在不让未来失效的情况下改变。

适应你的场景,它可能是这样的:

代码语言:javascript
运行
复制
template<typename C>
std::future<void> post_with_future(C&& handler)
{
    std::promise<void> promise;
    auto future = promise.get_future();

    auto wrapper = [promise{std::move(promise)}]{ // maybe mutable required?
         handler();
         promise.set_value();
    };

    // need to move in, cause the promise needs to be transferred. (i think)
    asio::post(strand, std::move(wrapper)); 
    return future;
}

我很高兴能得到一些对这些台词的反馈,因为我自己只是在学习所有的东西:)

希望能帮上忙,玛蒂

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49950679

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档