0

多数のワーカー スレッドを開始する関数があります。各ワーカー スレッドはオブジェクトによってカプセル化されており、そのオブジェクトのデストラクタがjoinスレッドを試行します。つまり、 を呼び出しますif (thrd_.joinable()) thrd_.join();。しかし、各労働者がどれだけの仕事をしなければならないかはアプリオリにはわかりません。管理関数は、ミューテックスと条件変数を使用して作業単位をスレッドに割り当てます。行う作業がこれ以上ない場合、ミューテックスが保持されている間に特定のフラグが設定され、条件変数でブロックされているすべてのスレッドに通知されるため、スレッドはウェイクアップし、変更されたフラグに気づき、シャットダウンします。

メインスレッドに例外があっても、このシャットダウンが機能するようにします。Java では、finally句を使用して常にフラグを設定し、作業処理ループの最後にスレッドに通知します。C++ には がないためfinally、独自の置換を作成しました。

class FinallyGuard {
private:
  std::function<void()> f_;
public:
  FinallyGuard(std::function<void()> f) : f_(f) { }
  ~FinallyGuard() { f_(); }
};

void Manager::manageWork(unsigned NumWorkers) {
  // Order matters: destructors are called in reverse order and will
  // 1. release the mutex lock so that workers can proceed
  // 2. unblock all threads using the finally workalike
  // 3. destroy the workers and join their threads
  std::forward_list<Worker> workers;
  FinallyGuard signalEndGuard([this] {
    std::unique_lock<std::mutex> lk(mtx_);
    done_ = true;
    beginWork_.notify_all();
  });
  std::unique_lock<std::mutex> lk(mtx_);
  for (unsigned i = 0; i != numWorkers; ++i)
    workers.emplace_front(this);
  while (haveMoreWork()) {
    // …
  }
}

しかし、ここでは明らかに他の言語の概念を考えています。これを達成するためのよりC++のような方法はありますか? 解決策としては、メソッドからの通常の戻りと例外がスローされた場合の両方で何らかのコードを実行するか、フラグと条件変数の組み合わせの代わりにワーカーをウェイクアップするためのより良いメカニズムを提供する必要があります。

4

2 に答える 2

1

コア言語にはありませんが、C++ には try finally に相当するものがあります。これは、C++ 分野の「ロックスター」の 1 人である Andrej Alexandrescu によって最初に作成された ScopeGuard と呼ばれます。ここで彼は、C++ and Beyond カンファレンス 2012 で新しいバージョンを発表します http://channel9.msdn.com/Shows/Going+Deep/C-and-Beyond-2012-Andrei-Alexandrescu-Systematic-Error-Handling-in-C

さらに重要なのは、コードです: https://gist.github.com/KindDragon/4650442

あなたの例はほとんど同じことをします。他の C++ プログラマーにあなたの意味を理解してもらいたい場合は、これを ScopeGuard と呼ぶか、Alexandrescus コードを使用する必要があります (これは、ライブラリーまたは共通のインクルードに入れる必要があり、頻繁に使用されます)。C++ プログラマーはすべてに RAII を使用します。私の考えでは、意図を表現することが重要です。

SCOPE_EXIT {
    std::unique_lock<std::mutex> lk(mtx_);
    done_ = true;
    beginWork_.notify_all();
};

あなたの場合。

私が働いている場所では、ScopeGuard は優れたスタイルと見なされており、コード レビューに問題なく合格しています。商業的に使用したい場合は、パブリック ドメインでもあります。

于 2013-03-05T17:00:29.337 に答える
0

C ++の方法は、RAIIと呼ばれるものを使用することです。一部のコードが常に実行されるようにするために、デストラクタが常に呼び出されるという事実を使用します。

于 2013-03-05T17:07:00.990 に答える