将 Boost 链与 std::future 结合使用
Use Boost strand in conjunction with std::future
我遇到过一个用例,我想将Boost链与std::future结合使用。
为了减少代码重复,我编写了一个通用函数,它将任务发布到提升链并返回未来。
// Some definitions first...
typedef boost::asio::io_service::strand cb_strand;
typedef std::shared_ptr< cb_strand > cb_strand_ptr;
代码如下所示:
//////////////////////////////////////////////////////////////////////////
template <class Task>
auto post_future_to_strand(cb_strand_ptr apStrand, Task task)
{
using return_type = decltype(task());
auto promise = std::make_shared<std::promise<return_type>>();
auto future = promise->get_future();
apStrand->wrap
(
[promise, task]()
{
try
{
promise->set_value(task());
}
catch (...)
{
// LOG ERROR ...
// NOTE: Exceptions can be thrown when setting the exception!
try
{
promise->set_exception(std::current_exception());
}
catch (...)
{
//LOG ERROR ...
}
}
}
);
return future;
};
然后,我希望将未来发布到一个链上,如以下示例所示:
std::future<int> f = post_future_to_strand(m_apStrand, std::bind(&foo::bar, this))
std::cout << "foo::bar() -> int is " << f.get() << std::endl;
不幸的是,我收到运行时异常:
terminate called after throwing an instance of 'std::future_error'
what(): std::future_error: Broken promise
Signal: SIGABRT (Aborted)
阅读文档后,我想我明白什么是违背承诺以及情况是如何产生的;但是,我觉得我正在 lambda 中捕捉承诺,所以一切都应该很好。 我是这个lambdas世界的新手,所以也许我的理解是错误的。
- Ubuntu Zesty
- GCC 6.3(配置为带 cmake 的 C++14(
你包装了任务,但你从不发布它。因此,包装后的任务会立即被破坏,并随之而来的是承诺。
还有另一个陷阱,只有当您在与将来阻塞的线程不同的线程上运行io_service时,事情才有效......否则,您将创建死锁:
- 生活在科里鲁死锁上
现在您有多个线程,您需要避免服务在首先发布任务之前退出的争用条件。
奖金:
我建议对包装器进行更简单的操作:
template <typename Task> auto post_future_to_strand(cb_strand_ptr apStrand, Task task) { auto package = std::make_shared<std::packaged_task<decltype(task())()> >(task); auto future = package->get_future(); apStrand->post([package] { (*package)(); }); return future; }
完整演示
住在科里鲁
#include <boost/asio.hpp>
#include <future>
#include <iostream>
using cb_strand_ptr = boost::asio::strand*;
//////////////////////////////////////////////////////////////////////////
template <typename Task>
auto post_future_to_strand(cb_strand_ptr apStrand, Task task)
{
auto package = std::make_shared<std::packaged_task<decltype(task())()> >(task);
auto future = package->get_future();
apStrand->post([package] { (*package)(); });
return future;
}
struct Foo {
boost::asio::strand s;
cb_strand_ptr m_apStrand = &s;
Foo(boost::asio::io_service& svc) : s{svc} {}
void do_it() {
std::future<int> f = post_future_to_strand(m_apStrand, std::bind(&Foo::bar, this));
std::cout << "foo::bar() -> int is " << f.get() << std::endl;
}
int bar() {
return 42;
}
};
int main() {
boost::asio::io_service svc;
auto lock = std::make_unique<boost::asio::io_service::work>(svc); // prevent premature exit
std::thread th([&]{ svc.run(); });
Foo foo(svc);
foo.do_it();
lock.reset(); // allow service to exit
th.join();
}
指纹
foo::bar() -> int is 42
相关文章:
- 多态性和功能结合
- 架构决策:返回std::future还是提供回调
- 使用用户定义的参数调用future/async并调用类方法
- 将 Vulkan 与 SFML 结合使用?
- 将 c++ 生成器应用程序与外部 dll 结合使用
- 如何将增强MSM与增强信号结合使用?
- std::p romise::set_value() 和 std::future::wait() 是否提供内存围栏?
- 修改在 std::future 的 lambda 中引用捕获的值
- MS Visual Studio 解决方案结合了非托管C++项目和 C# 项目
- 函数未在作用域中声明 / 如何结合使用 header.h、header.cpp 和 main.cpp?
- 从 T 创建 std::future 的最佳方式<T>
- C++ std::future没有被调用
- 对于等待以 std::future wait() 返回的函数的 CPU 使用率或检查标志在循环中休眠一段时间哪个更好?
- 将预编译的 C 共享库与 JNI/NDK 结合使用
- C++ 将函数指针与最佳性能相结合
- 如何使用 boost::future 重新抛出 std::exception_ptr 存储的原始异常?
- 将 Lua 与 C++ DLL 结合使用
- 为什么push_back和emplace_back结合在一起时,会有不同的行为
- 将 aws-iot-device-sdk-cpp-v2 与 CMake 结合使用
- 将 Boost 链与 std::future 结合使用