我使用的是Boost 1.66.0,其中asio内置了对期货互操作的支持(而且已经有一段时间了)。我在网上看到的示例说明了如何在使用网络功能(如async_read
、async_read_some
等)时干净地实现这一点。这是通过提供boost::asio::use_future
代替完成处理程序来实现的,这将导致启动函数按预期返回future
。
为了从boost::asio::post
获得相同的行为,需要提供或包装函数的对象是什么?
我发布该工作的目的是在一个链的上下文中执行它,但在其他情况下等待工作完成,这样我就可以得到我想要做的行为:
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行为。
是否有包装器或具有必要特征的东西来获得我想要的行为,还是我需要自己来定义它?
发布于 2021-11-17 16:09:34
@MartiNitro's idea with packaged_task
已经成为库的一部分:现在您只需发布一个packaged_task
,它将神奇地返回它的未来:
auto f = post(strand_, std::packaged_task<int()>(task));
#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();
}
打印
Hello world
Answer: 42
发布于 2020-06-25 16:29:11
这是我想出来的,它本质上是将asio::post
和插件封装在一个承诺/未来的对子中。我认为它也能适应你的需要。
// 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;
}
承诺可以在不让未来失效的情况下改变。
适应你的场景,它可能是这样的:
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;
}
我很高兴能得到一些对这些台词的反馈,因为我自己只是在学习所有的东西:)
希望能帮上忙,玛蒂
https://stackoverflow.com/questions/49950679
复制相似问题