【问题标题】:How do you post a boost packaged_task to an io_service in C++03?如何在 C++03 中将 boost packaged_task 发布到 io_service?
【发布时间】:2012-10-20 21:14:28
【问题描述】:

这是上一个问题 (here) 的后续问题,但我正在开发一个多线程应用程序,我想将 Boost packaged_task 发布到线程化 io_service。我被困在使用 C++03 编译器(所以 std::move 不可用),并且 packaged_task 不可复制。我已经尝试将它包装在 shared_ptr 中并传递它,以及许多其他的东西。这是我当前的尝试和随后的编译器错误。知道如何让它工作吗?

boost::asio::io_service io_service;
boost::thread_group threads;
boost::asio::io_service::work work(io_service);
for (int i = 0; i < maxNumThreads; ++i)
{
    threads.create_thread(boost::bind(&boost::asio::io_service::run,
        &io_service));
}
std::vector<boost::shared_future<bool> > pending_data; // vector of futures

bool process_data(int,int){...}
...

for(int theTime = 0; theTime != totalScenarioTime; ++theTime)
{
    for(int i = 0; i < numSmallTasks; ++i)
    {
        boost::packaged_task<bool> task(boost::bind(&process_data,i,theTime));
        boost::shared_future<bool> fut(task.get_future());
        pending_data.push_back(fut); // C++11 possible: (std::move(fut) when fut is a unique_future);
        io_service.post(task); // C++11 possible: (std::move(task));    
    }
    // After loop - wait until all futures are evaluated
    boost::wait_for_all(pending_data.begin(), pending_data.end()); 
    pending_data.clear();
}

这会导致:

In file included from ../boostlibs/boost/asio/io_service.hpp:767:0,
             from ../boostlibs/boost/asio/basic_io_object.hpp:19,
             from ../boostlibs/boost/asio/basic_socket.hpp:19,
             from ../boostlibs/boost/asio/basic_datagram_socket.hpp:20,
             from ../boostlibs/boost/asio.hpp:20,
             from ../main.cpp:13:
../boostlibs/boost/asio/impl/io_service.hpp: In member function ‘void boost::asio::io_service::post(const CompletionHandler&) [with CompletionHandler = boost::packaged_task<bool>]’:
../main.cpp:256:23:   instantiated from here
../boostlibs/boost/asio/impl/io_service.hpp:95:67: error: no matching function for call to ‘boost::packaged_task<bool>::packaged_task(const boost::packaged_task<bool>&)’
../boostlibs/boost/asio/impl/io_service.hpp:95:67: note: candidates are:
../boostlibs/boost/thread/future.hpp:1372:9: note: boost::packaged_task<R>::packaged_task(boost::detail::thread_move_t<boost::packaged_task<R> >) [with R = bool]
../boostlibs/boost/thread/future.hpp:1372:9: note:   no known conversion for argument 1 from ‘const boost::packaged_task<bool>’ to ‘boost::detail::thread_move_t<boost::packaged_task<bool> >’
../boostlibs/boost/thread/future.hpp:1318:9: note: boost::packaged_task<R>::packaged_task() [with R = bool]
../boostlibs/boost/thread/future.hpp:1318:9: note:   candidate expects 0 arguments, 1 provided
../boostlibs/boost/thread/future.hpp:1314:9: note: boost::packaged_task<R>::packaged_task(boost::packaged_task<R>&) [with R = bool, boost::packaged_task<R> = boost::packaged_task<bool>]
../boostlibs/boost/thread/future.hpp:1314:9: note:   no known conversion for argument 1 from ‘const boost::packaged_task<bool>’ to ‘boost::packaged_task<bool>&’
../boostlibs/boost/asio/detail/handler_type_requirements.hpp:95:26: error:   initializing argument 1 of ‘T& boost::asio::detail::lvref(T) [with T = boost::packaged_task<bool>]’
../boostlibs/boost/asio/impl/io_service.hpp:95:67: error: no matching function for call to ‘boost::packaged_task<bool>::packaged_task(const boost::packaged_task<bool>&)’
../boostlibs/boost/asio/impl/io_service.hpp:95:67: note: candidates are:
../boostlibs/boost/thread/future.hpp:1372:9: note: boost::packaged_task<R>::packaged_task(boost::detail::thread_move_t<boost::packaged_task<R> >) [with R = bool]
../boostlibs/boost/thread/future.hpp:1372:9: note:   no known conversion for argument 1 from ‘const boost::packaged_task<bool>’ to ‘boost::detail::thread_move_t<boost::packaged_task<bool> >’
../boostlibs/boost/thread/future.hpp:1318:9: note: boost::packaged_task<R>::packaged_task() [with R = bool]
../boostlibs/boost/thread/future.hpp:1318:9: note:   candidate expects 0 arguments, 1 provided
../boostlibs/boost/thread/future.hpp:1314:9: note: boost::packaged_task<R>::packaged_task(boost::packaged_task<R>&) [with R = bool, boost::packaged_task<R> = boost::packaged_task<bool>]
../boostlibs/boost/thread/future.hpp:1314:9: note:   no known conversion for argument 1 from ‘const boost::packaged_task<bool>’ to ‘boost::packaged_task<bool>&’
../boostlibs/boost/asio/detail/handler_type_requirements.hpp:96:32: error:   initializing argument 1 of ‘const T& boost::asio::detail::clvref(T) [with T = boost::packaged_task<bool>]’
../boostlibs/boost/asio/impl/io_service.hpp:97:3: error: no matching function for call to ‘boost::packaged_task<bool>::packaged_task(const boost::packaged_task<bool>&)’
../boostlibs/boost/asio/impl/io_service.hpp:97:3: note: candidates are:
../boostlibs/boost/thread/future.hpp:1372:9: note: boost::packaged_task<R>::packaged_task(boost::detail::thread_move_t<boost::packaged_task<R> >) [with R = bool]
../boostlibs/boost/thread/future.hpp:1372:9: note:   no known conversion for argument 1 from ‘const boost::packaged_task<bool>’ to ‘boost::detail::thread_move_t<boost::packaged_task<bool> >’
../boostlibs/boost/thread/future.hpp:1318:9: note: boost::packaged_task<R>::packaged_task() [with R = bool]
../boostlibs/boost/thread/future.hpp:1318:9: note:   candidate expects 0 arguments, 1 provided
../boostlibs/boost/thread/future.hpp:1314:9: note: boost::packaged_task<R>::packaged_task(boost::packaged_task<R>&) [with R = bool, boost::packaged_task<R> = boost::packaged_task<bool>]
../boostlibs/boost/thread/future.hpp:1314:9: note:   no known conversion for argument 1 from ‘const boost::packaged_task<bool>’ to ‘boost::packaged_task<bool>&’
../boostlibs/boost/asio/detail/impl/task_io_service.hpp:54:6: error:   initializing argument 1 of ‘void boost::asio::detail::task_io_service::post(Handler) [with Handler = boost::packaged_task<bool>]’

使用 boost::move(task) 会导致两个错误:

error: no match for call to ‘(boost::detail::thread_move_t<boost::packaged_task<bool> >) ()’
error: no match for call to ‘(boost::detail::thread_move_t<boost::packaged_task<bool> >) ()’

【问题讨论】:

  • 您使用哪个 Boost 版本?
  • 在 1.50 中 boost::move(task) 应该可以工作。
  • @Rost,@IgorR.,我使用的是 1.49,现在使用的是 1.51,使用 boost::move(task) 时仍然出现以下错误:../boost_1_51_0/boost/asio/handler_invoke_hook.hpp:64:3: error: no match for call to ‘(boost::detail::thread_move_t&lt;boost::packaged_task&lt;bool&gt; &gt;) ()’ 有什么想法吗?
  • @JohnDoe 奇怪的事情,你使用什么编译器/版本?
  • 糟糕,抱歉,没有注意到您尝试postio_service::post 复制它的参数,所以 move 无济于事。唯一的方法是动态分配任务并传递它的(共享)指针——就像@Rost 推荐的那样。

标签: multithreading boost boost-asio future


【解决方案1】:

boost::packaged_task 支持 boost::move,因为 Boost 版本 1.50,请参阅相应的 ticket

但问题是io_service::post 完成处理程序参数必须是CopyConstructible,如Asio handler requirements 中所述。因此boost::packaged_task不能直接发布或移动。 (感谢Igor R. 提供此问题)。

有使用指针的解决方法,例如你可以用boost::shared_ptr 包裹boost::packaged_task 并将其绑定到operator()

 typedef boost::packaged_task<bool> task_t;
 boost::shared_ptr<task_t> task = boost::make_shared<task_t>(
    boost::bind(&process_data, i, theTime));

 io_service.post(boost::bind(&task_t::operator(), task));

【讨论】:

  • 您将 operator() 绑定到共享指针的解决方法有效。非常感谢您在这方面的帮助!
  • 我很想知道这对使用 VC++10 的人来说是如何公平的。虽然共享打包任务似乎在 posix(mac clang 和 linux gcc)上运行良好,但我在 windows 上遇到非常奇怪的错误 --> 'member function already defined or declared'
  • @BenJ 我刚刚在 VC2010 上使用 Boost 1.53 编译了这段代码,它编译和工作正常(future.hpp 中的 C4913 警告除外,但这是已知的 Boost 问题)。您能否发布您的实际代码?
  • 谢谢 Rost,是的,这是我的错误。不幸的是,我不得不使用 boost 1_49,我发现它对于 packaged_tasks 和 shared_futures 非常有问题,如果启用了 c++11 编译则更是如此。这些问题似乎已在更高版本的 boost 中得到修复
猜你喜欢
  • 1970-01-01
  • 2016-02-27
  • 2012-09-25
  • 2015-07-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-22
相关资源
最近更新 更多