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

履歴 編集

function
<barrier>

std::barrier::コンストラクタ(C++20)

constexpr explicit
barrier(ptrdiff_t expected,
        CompletionFunction f = CompletionFunction()); // (1)

barrier(const barrier&) = delete;                     // (2)

barrierオブジェクトの構築

  • (1) : barrierオブジェクトの初期化を行う。
  • (2) : コピーコンストラクタ。コピー不可。

説明のため、ここではバリアオブジェクトが保持するCompletionFunction型のメンバ変数をcompletionと表記する。

事前条件

expected >= 0 かつ expected <= max()

効果

各バリアフェーズの初期予定カウントと、初回フェーズにおける現行予定カウントの両方にexpectedを設定する。 completionstd::move(f)で初期化する。 初回フェーズを開始する。

例外

CompletionFunction型のムーブコンストラクタが投げた例外

備考

expected0として初期化したバリアオブジェクトでは、破棄以外の操作を行えない。

#include <barrier>
#include <iostream>
#include <thread>
#include <mutex>

// 行単位cout出力用ロックを返す(対応コンパイラ登場までの暫定措置)
// C++20で追加されたstd::osyncstreamの方が好ましい。
//   std::osyncstream(std::cout) << ...;
auto lk() {
  static std::mutex cout_mtx;
  return std::unique_lock{cout_mtx};
}

int main() {
  // (完了関数なし)バリアを定義
  std::barrier<> sync1{2};

  // 完了関数付きのバリアを定義
  std::barrier sync2{2, []{
    // 完了関数はバリアに関与するいずれか一つのスレッド上でのみ実行されること保証される
    std::cout << "finished @" << std::this_thread::get_id() << std::endl;
  }};

  // 並行実行されるタスクを定義
  auto task = [&]{
    lk(), std::cout << "phase-1  @" << std::this_thread::get_id() << std::endl;
    sync2.arrive_and_wait();
    lk(), std::cout << "phase-2  @" << std::this_thread::get_id() << std::endl;
    sync2.arrive_and_wait();
    lk(), std::cout << "phase-3  @" << std::this_thread::get_id() << std::endl;
    sync1.arrive_and_wait();
  };

  // タスクを2並行実行
  std::thread t{task};
  task();
  t.join();
}

出力例

phase-1  @140171090683648
phase-1  @140171067340544
finished @140171067340544
phase-2  @140171067340544
phase-2  @140171090683648
finished @140171090683648
phase-3  @140171090683648
phase-3  @140171067340544

バージョン

言語

  • C++20

処理系