简体   繁体   English

Boost :: ASIO和std :: packaged_task

[英]Boost::ASIO and std::packaged_task

I have the following pieces of C++14 code 我有以下C ++ 14代码

boost::asio::io_service service_;

I want to submit pieces of work into the io_service , using the following code that takes any function, it's input arguments and returns me a std::future to the return value. 我想使用下面的代码将任何工作提交到io_service ,该代码可以使用任何函数,它是输入参数,并向我返回一个std::future到返回值。

template <typename F, typename... Args>
auto enqueue(F &&f, Args &&... args) -> std::future<typename std::result_of<F(Args...)>::type> {
  typedef typename std::result_of<F(Args...)>::type rType;
  auto task = std::make_shared<std::packaged_task<rType()>>(std::bind(std::forward<F>(f),
                                                                       std::forward<Args>(args)...));
  std::future<rType> res = task->get_future();
  service_.post(task);
  return res;
}

This was then called using 然后使用

enqueue([] (int i) {
  return i+1;
}, 100);

This doesnt seem to be working. 这似乎不起作用。 I get an error saying that service_.post() was not expecting this input. 我收到一条错误消息,说service_.post()不需要此输入。

xxxxxxxxxxxxxx:49:3:   required from ‘std::future<typename std::result_of<_Functor(_ArgTypes ...)>::type> enqueue(F&&, Args&& ...) [with F = main()::<lambda()>::<lambda()>; Args = {int}; typename std::result_of<_Functor(_ArgTypes ...)>::type = int]’
xxxxxxxxxxxxxx:44:6:   required from here
/usr/include/boost/asio/impl/io_service.hpp:102:3: error: static assertion failed: CompletionHandler type requirements not met
   BOOST_ASIO_COMPLETION_HANDLER_CHECK(CompletionHandler, handler) type_check;
   ^
/usr/include/boost/asio/impl/io_service.hpp:85:3: error: no match for call to ‘(std::shared_ptr<std::packaged_task<void()> >) ()’
   BOOST_ASIO_COMPLETION_HANDLER_CHECK(CompletionHandler, handler) type_check;
   ^

As far as I understand the boost::asio documentation, this can be done. 据我了解boost::asio文档,可以做到这一点。 Any ideas? 有任何想法吗?

From the documentation for post() : post()的文档中:

handler 处理器

The handler to be called. 要调用的处理程序。 The io_service will make a copy of the handler object as required. io_service将根据需要复制处理程序对象。 The function signature of the handler must be: void handler(); 处理程序的功能签名必须为: void handler();

You are passing in a std::shared_ptr<std::packaged_task<int()>> . 您正在传递std::shared_ptr<std::packaged_task<int()>> A shared_ptr doesn't have operator() defined. shared_ptr没有定义operator() And packaged_task unwrapped isn't copyable. 并且已packaged_task无法复制。

So in order to make this work, you'll have to make a shared_ptr<promise> : 因此,为了使这项工作有效,您必须创建一个shared_ptr<promise>

using R = std::result_of_t<F(Args&&...)>;
auto promise = std::make_shared<std::promise<R>>();
std::future<R> res = promise->get_future();

service.post([promise = std::move(promise),
    f = std::forward<F>(f),
    args = std::make_tuple(std::forward<Args>(args)...)]{
        promise->set_value(std::experimental::apply(f, args));    
    });
return res;

I seem to remember having been bitten by this myself. 我似乎记得自己曾被我咬过。 It's because std::packaged_task is not copyable (the copy constructor is explicitly deleted). 这是因为std::packaged_task是不可复制的(复制构造函数已显式删除)。

This is because it contains a promise, which is also not copyable - only moveable. 这是因为它包含一个承诺,该承诺也不能复制-只能移动。

asio::io_service demands that handler objects are copyable. asio::io_service要求处理程序对象是可复制的。

You may want to consider building your own packaged-task-like function object which keeps a shared_ptr to the promise. 您可能要考虑构建自己的类似于打包任务的函数对象,该对象将shared_ptr保留为promise。 That would be copyable. 那将是可复制的。

The non-void return type is a red herring - don't waste your time with that. 非无效返回类型是红色鲱鱼-不要浪费时间。

documentation of packaged task here: http://en.cppreference.com/w/cpp/thread/packaged_task/packaged_task 打包任务的文档在这里: http : //en.cppreference.com/w/cpp/thread/packaged_task/packaged_task

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM