2011-11-14 5 views
2

私はアプリケーションでスレッドと同期のためのブーストライブラリを使用しています。クロススレッドでのC++の同期と例外処理

まず第一に、同期のスレッド内の例外は私にとってcompilitey新しいことです。 以下のいずれの場合でも、私が達成したいと思っている疑似コードがあります。私は同期スレッドが、通知を行うスレッドからスローされた可能性がある同じ例外をスローする必要があります。どうすればこれを達成できますか?

は、事前にブーストスレッドモデルに

感謝を用いたクロススレッドの相互作用を投げる例外に関するスタックオーバーフローから任意のトピックを見つけることができませんでした!

答えて

1

// mutex and scondition variable for the problem 
mutable boost::mutex conditionMutex; 
mutable boost::condition_variable condition; 

inline void doTheThing() const { 

    if (noone doing the thing) { 
     try { 
      doIt() 
      // I succeeded 
      failed = false; 
      condition.notify_all(); 
     } 
     catch (...) { 
      // I failed to do it 
      failed = true; 
      condition.notify_all(); 
      throw 
     } 
    else { 
     boost::mutex::scoped_lock lock(conditionMutex); 
     condition.wait(lock); 
     if (failed) { 
      // throw the same exception that was thrown from 
      // thread doing notify_all 
     } 
    } 

は}だから、doTheThing()を打つ最初のスレッドがdoIt()を呼びたい、とdoTheThing()を打つすべての後続のスレッドは、彼らが進む前にdoIt()を呼び出して終了する最初のスレッドを待ちます。

私は、これはトリックやるべきだと思う:

boost::mutex conditionMutex; // mutable qualifier not needed 
bool failed = false; 
bool done = false; 

inline void doTheThing() const { 

    boost::unique_lock uql(conditionMutex); 

    if (!done) { 
     done = true; 
     try { 
      doIt(); 
      failed = false; 
     } 
     catch (...) { 
      failed = true; 
      throw 
     } 
    } 
    else if (failed) 
    { 
     uql.unlock(); 
     // now this thread knows that another thread called doIt() and an exception 
     // was thrown in that thread. 
    } 

} 

重要事項:

doTheThing()がロックを取る必要があります呼び出すすべてのスレッドを。これを回避する方法はありません。あなたはスレッドを同期させており、スレッドは別のスレッドで何が起きているかを知るために、ロックを取らなければなりません。 (または原子メモリ操作を使用することもできますが、それはより高度な技術です)。faileddoneという変数はconditionMutexによって保護されています。

例外をスローすることによって、関数が通常またはを終了すると、C++はデストラクタをuqlとして呼び出します。

EDITああ、他のすべてのスレッドに例外を投げるのは、それを忘れて、ほとんど不可能で、C++でのやり方ではありません。代わりに、各スレッドは、先に示したところで最初のスレッドがdoIt()を正常に呼び出すかどうかを確認できます。

EDIT例外を別のスレッドに伝播するための言語サポートはありません。 の伝搬例外を別のスレッドに渡すと、メッセージは別のスレッドに渡されます。スレッド(boost::asio::io_service::post())間でメッセージを渡す問題に対するライブラリソリューションはたくさんあります。例外を含むメッセージを渡し、メッセージの受信時にその例外をスローする方法があります。しかし、それは悪い考えです。エラーが発生した場合にのみ例外をスローして、通常の関数呼び出しでコールスタックを解くことを防ぎます。それは例外です。普通の方法を返すときに関数から戻る別の方法は意味をなさない。

+0

お返事ありがとうございます。私はif文をロックして、他の人に渡す必要があることを知っています。私はちょうど擬似コードからのロックアウトを残しました。あなたのソリューションは、すべてのスレッドがdoIt()を通過する必要があるという要件を持っています。私は、ブロックされたスレッドが、何をしているのかを作業スレッドが終了するのを待つようにします。実際の問題は、同期スレッドに可能性のある例外をどのように伝播するかにありました。あなたはこれが全く不可能だと言っていますか? – Lauri

+0

@Lauri 1 of 2:注意深く見てください。最初のスレッドだけが 'doIt()'を通過し、残りのスレッドは 'done'をチェックした後に' doIt() 'をスキップします。 –

+0

@Lauri 2 of 2:私は私の答えを明らかにしました、上記を参照してください。 –