• Class / Function / Type

      std::
    • Header file

      <>
    • Other / All

    最終更新日時(UTC):
    が更新

    履歴 編集

    class
    <latch>

    std::latch

    namespace std {
      class latch;
    }
    

    概要

    latchクラスは、ラッチ通過/到達スレッドが期待する個数になるまで複数スレッドの進行をブロックする、スレッド調整機構(同期プリミティブ)である。

    ラッチは1つのカウンタで状態管理される同期プリミティブとみなせる。カウンタは0以上かつ初期値以下の値をとり、このカウンタ値がラッチ未到達のスレッド個数と解釈される。 その動作仕様からカウントダウン・ラッチと呼ばれることもある。

    • コンストラクタにてカウンタ値を設定する。
    • count_down()によりカウンタ値の減算と通知を行う。(ラッチ通過)
    • wait()によりカウンタ値が0になるまで呼び出しスレッドをブロックする。(ラッチ待機)
    • arrive_and_wait()count_down()wait()に相当する。(ラッチ到達 兼 待機)

    ラッチオブジェクトは1回だけ使用でき、カウンタ値が0に到達したオブジェクトの再利用はできない。 複数スレッド間同期を繰り返しとる場合はバリアbarrierを利用する。

    ラッチlatchはカウンタ値0を待機するが、類似機構のセマフォcounting_semaphoreはカウンタ値が0より大きいことを待機するという違いがある。

    メンバ関数

    名前 説明 対応バージョン
    (constructor) コンストラクタ C++20
    (destructor) デストラクタ C++20
    operator=(const latch&) = delete; 代入演算子 C++20
    count_down 通過通知 C++20
    try_wait カウンタ値が0か否かを確認 C++20
    wait 待機処理 C++20
    arrive_and_wait 到達通知と待機処理 C++20

    静的メンバ関数

    名前 説明 対応バージョン
    max 処理系でサポートされるカウンタ最大値 C++20

    #include <iostream>
    #include <latch>
    #include <mutex>
    #include <thread>
    
    constexpr int NWORKER = 3;  // ワーカ数
    
    std::mutex cout_mtx;  // 行単位cout出力用ミューテックス
    
    int main()
    {
      // 1回だけ初期化される共有データ
      int shared_data = 0;
    
      // 初期化済みを表すラッチ: 初期カウント値=1
      std::latch initialized{1};
      // タスク完了を表すラッチ: 初期カウント値=ワーカ数+1(メインスレッド)
      std::latch completed{NWORKER+1};
    
      // ワーカスレッド群をFire-and-Forget起動
      for (int id = 1; id <= NWORKER; id++) {
        std::thread([&,id]{
          // 共有データの初期化完了を待機
          initialized.wait();
          // メインスレッド上でのshared_data代入完了は保証されており、
          // 以降はshared_data読出のみであればデータ競合発生しない。
          int local_data = shared_data;
    
          { // ワーカスレッドのタスクを実行
            std::lock_guard lk{cout_mtx};
            std::cout << "Worker#" << id << ":" << local_data << std::endl;
          }
    
          // タスク完了を通知
          completed.count_down();
          // ワーカスレッドはブロックされずそのまま終了する
        }).detach();
      }
    
      // 共有データを初期化
      shared_data = 42;
    
      // 共有データ初期化完了をワーカスレッド群へ通知
      initialized.count_down();
      // メインスレッドはブロックされず後続行を実行する
    
      { // メインスレッドのタスクを実行
        std::lock_guard lk{cout_mtx};
        std::cout << "Main:" << shared_data << std::endl;
      }
    
      // メインスレッドのタスク完了通知 兼 全ワーカスレッドのタスク完了待機
      completed.arrive_and_wait();
    }
    

    出力例

    Worker#1:42
    Worker#2:42
    Main:42
    Worker#3:42
    

    バージョン

    言語

    • C++20

    処理系

    関連項目

    参照