2

アプリケーションでスレッド化と同期にブースト ライブラリを使用しています。

まず第一に、同期時のスレッド内での例外は、私にとってコンパイルの新しいことだと言わなければなりません。いずれにせよ、以下は私が達成したい疑似コードです。通知を行っているスレッドからスローされた可能性があるのと同じ例外をスローする同期スレッドが必要です。どうすればこれを達成できますか?

ブースト スレッド モデルを使用したクロス スレッド インタラクションによる例外のスローに関するスタック オーバーフローのトピックが見つかりませんでした

よろしくお願いします!

// 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
       }
  }

}

4

1 に答える 1

1

したがって、ヒットした最初のスレッドがdoTheThing()call を呼び出し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、関数が正常に終了するとき、または例外をスローすることによって、のデストラクタを呼び出します。

編集ああ、他のすべてのスレッドに例外をスローすることについては、それを忘れてください。それはほとんど不可能であり、C ++で行われる方法ではありません。代わりに、各スレッドは、最初のスレッドが上記の場所で正常に呼び出されたかどうかを確認できますdoIt()

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

于 2011-11-14T18:24:55.610 に答える