2011-06-03 3 views
3

私はスレッドプールで多くのジョブを実行する必要があるC++プロジェクトに取り組んでいます。ジョブは失敗する傾向があります。つまり、完了後に各ジョブがどのように終了するかを知る必要があります。 Javaプログラマーの大部分は、Javaのutil.concurrentパッケージのさまざまなクラスに似た、 "先物"や同様のパラダイムを使用する考えが好きです。"先物"または同様のパラダイムを持つC++並行性ライブラリの開発

私は2つの質問があります:まず、これは既にC++のために存在していますか(私はBoostでは何も見つかりませんでしたが、第二に、これはC++の正気なアイデアですか?

私はここで達成しようとしているかの簡単な例を見つけました:

http://www.boostcookbook.com/Recipe:/1234841

このアプローチは理にかなっていますか?

+1

このように、スレッド間で結果を渡す方法について説明しています。スレッドはメモリを共有しているため、それらはすべてあなたのコントロール下にあります。なぜ、これにメタ構造を適用する必要がありますか?単に結果を含む具体的なクラスを作成し、結果が得られたときに通知するのはなぜでしょうか。 – Jay

+1

偉大な質問、ジェイ。先物パラダイムを使用する本当の理由は、非同期タスクから結合スレッドに例外を持ち込むことができるようにすることです。 – Tom

答えて

5

先物は、両方の次期標準(C++ 0xの)とブーストの内部に存在しています。メイン・ネームfutureは同じですが、他のタイプを見つけてセマンティクスを理解するためには、ドキュメントを読む必要があります。私はJavaの先物を知らないので、もしそうならば、どこが違うのかは分かりません。

ブーストのライブラリはAnthony Williamsで書かれていますが、これは標準のその部分の定義にも関係していたと思います。彼はまた、C++ Concurrency in Actionと書いてあります。これには、先​​物、タスク、約束事、および関連するオブジェクトの説明が含まれています。彼の会社では、C++ 0xスレッディング・ライブラリの完全実装と実装まで、興味があれば販売しています。

+0

情報ありがとうございます。このため、プロジェクトをC++ 0xに具体的に移行しました。 – Tom

+0

この回答は正しいですが、「wait_for_any」と「wait_for_all」という便利な機能を提供するため、ブースト版の使用を検討することもできます。 – tgoodhart

+0

更新:私たちは何とか後押しするために戻ってしまった。それにもかかわらず、両方の情報に感謝します。 – Tom

-1

C++テンプレートはJavaジェネリックスに比べて制限が少ないため、「未来はそれらとスレッド同期プリミティブで容易に移植できます。そのような仕組みをサポートする既存の図書館については、うまくいけば誰かがそれを知っていることでしょう。

5

ブーストはfutures and other threading tools implementedです。

boost::unique_futureget()メソッドを呼び出すと、非同期実行中にその中に格納されていた可能性のある例外がすべて再スローされることに注意してください。

私はあなたのような何かをすることをお勧め:

#pragma once 

#include <tbb/concurrent_queue.h> 

#include <boost/thread.hpp> 
#include <boost/noncopyable.hpp> 

#include <functional> 

namespace internal 
{ 
    template<typename T> 
    struct move_on_copy 
    { 
     move_on_copy(const move_on_copy<T>& other) : value(std::move(other.value)){} 
     move_on_copy(T&& value) : value(std::move(value)){} 
     mutable T value; 
    }; 

    template<typename T> 
    move_on_copy<T> make_move_on_copy(T&& value) 
    { 
     return move_on_copy<T>(std::move(value)); 
    } 
} 

class executor : boost::noncopyable 
{ 
    boost::thread thread_; 

    tbb::concurrent_bounded_queue<std::function<void()>> execution_queue_; 

    template<typename Func> 
    auto create_task(Func&& func) -> boost::packaged_task<decltype(func())> // noexcept 
    { 
     typedef boost::packaged_task<decltype(func())> task_type; 

     auto task = task_type(std::forward<Func>(func));    

     task.set_wait_callback(std::function<void(task_type&)>([=](task_type& my_task) // The std::function wrapper is required in order to add ::result_type to functor class. 
     { 
      try 
      { 
       if(boost::this_thread::get_id() == thread_.get_id()) // Avoids potential deadlock. 
        my_task(); 
      } 
      catch(boost::task_already_started&){} 
     })); 

     return std::move(task); 
    } 

public: 

    explicit executor() // noexcept 
    { 
     thread_ = boost::thread([this]{run();}); 
    } 

    ~executor() // noexcept 
    { 
     execution_queue_.push(nullptr); // Wake the execution thread. 
     thread_.join(); 
    } 

    template<typename Func> 
    auto begin_invoke(Func&& func) -> boost::unique_future<decltype(func())> // noexcept 
    { 
     // Create a move on copy adaptor to avoid copying the functor into the queue, tbb::concurrent_queue does not support move semantics. 
     auto task_adaptor = internal::make_move_on_copy(create_task(func)); 

     auto future = task_adaptor.value.get_future(); 

     execution_queue_.push([=] 
     { 
      try{task_adaptor.value();} 
      catch(boost::task_already_started&){} 
     }); 

     return std::move(future);  
    } 

    template<typename Func> 
    auto invoke(Func&& func) -> decltype(func()) // noexcept 
    { 
     if(boost::this_thread::get_id() == thread_.get_id()) // Avoids potential deadlock. 
      return func(); 

     return begin_invoke(std::forward<Func>(func), prioriy).get(); 
    } 

private: 

    void run() // noexcept 
    { 
     while(true) 
     { 
      std::function<void()> func; 
      execution_queue_.pop(func); 
        if(!func) 
         break; 
      func(); 
     } 
    } 
}; 
関連する問題