2012-10-31 21 views
11

これは以前の質問(here)の後継ですが、私はマルチスレッドアプリケーションに取り組んでおり、Boost packaged_taskをスレッド化されたio_serviceに投稿したいと思います。私はC++ 03コンパイラを使用しているので(std :: moveが出ているので)、packaged_taskはコピーできません。私はshared_ptrでそれをラップし、それを渡すことを試みました、そして、他の多くのもの。ここに私の現在の試みとその後のコンパイラエラーがあります。どのようにこれを動作させるための任意のアイデアですか?どのようにC++ 03のio_serviceにboost packaged_taskを投稿しますか?

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>]’ 

::移動の2つのエラーで(タスク)の結果:

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> >)()’ 
+0

どのブーストバージョンあなたは使いますか? – Rost

+1

1.50ではboost :: move(task)が動作するはずです。 –

+0

@Rost、@IgorR。、私は1.49を使用していましたが、現在は1.51を使用していますが、boost :: move(task)を使用しても次のエラーが表示されます: '../boost_1_51_0/boost/asio/handler_invoke_hook.hpp:64: 3:エラー: '(boost :: detail :: thread_move_t >)(')のエラーはありません。 –

答えて

14

boost::packaged_taskticketを対応する参照、ブースト・バージョン1.50以降boost::moveをサポートしています。

しかし、問題はio_service::post完了ハンドラパラメータがAsio handler requirementsに記載されたCopyConstructibleでなければならないということです。したがって、boost::packaged_taskは直接または移動することによって転記することはできません。 (この問題はIgor R.に感謝します)。

ポインタを使用した回避策があります。あなたはboost::shared_ptrboost::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)); 
+0

operator()を共有ポインタにバインドするという回避策が働いています。あなたの助けを借りて! –

+0

私は非常にVC++ 10を使用している人のためのこの見本市を知って興味があります。パッケージされた共有タスクはposix(mac clangとlinux gcc)上でうまくいくようですが、 - > 'メンバ関数は既に定義または宣言されています' –

+0

@BenJ VC2010でBoost 1.53を使用してこのコードをコンパイルしました。コンパイルして正常に動作します(future.hppのC4913警告は例外ですが、これはBoostの既知の問題です)。 – Rost