名前空間
変種
操作

std::barrier

From cppreference.com
< cpp‎ | thread
 
 
並行性サポートライブラリ
スレッド
(C++11)
(C++20)
this_thread 名前空間
(C++11)
(C++11)
(C++11)
協調的なキャンセル
排他制御
(C++11)
汎用ロック管理
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
条件変数
(C++11)
セマフォ
ラッチとバリア
(C++20)
barrier
(C++20)
future
(C++11)
(C++11)
(C++11)
(C++11)
安全なメモリ解放 (Safe Reclamation)
(C++26)
ハザードポインタ
アトミック型
(C++11)
(C++20)
アトミック型の初期化
(C++11)(C++20で非推奨)
(C++11)(C++20で非推奨)
メモリオーダー
(C++11)(C++26で非推奨)
アトミック操作のためのフリー関数
アトミックフラグのためのフリー関数
 
 
ヘッダ <barrier> で定義
template< class CompletionFunction = /* 後述 */ >
class barrier;
(C++20以降)

クラステンプレート std::barrier は、既知のサイズのスレッドグループがバリアに到達するまで、そのグループ内のすべてのスレッドをブロックするスレッド協調メカニズムを提供します。std::latch とは異なり、バリアは再利用可能です。つまり、到着したスレッドのグループがブロック解除されると、そのバリアを再利用できます。std::latch とは異なり、バリアはスレッドをブロック解除する前に、空かもしれない呼び出し可能オブジェクトを実行します。

バリアオブジェクトの生存期間は、1つ以上のフェーズで構成されます。各フェーズは、待機中のスレッドがブロックするフェーズ同期点を定義します。スレッドは arrive を呼び出すことでバリアに到達できますが、フェーズ同期点での待機は遅延させることができます。そのようなスレッドは、後で wait を呼び出すことでフェーズ同期点でブロックできます。

バリアのフェーズは、以下のステップで構成されます。

  1. 期待カウントは、arrive または arrive_and_drop が呼び出されるたびにデクリメントされます。
  2. 期待カウントがゼロに達すると、フェーズ完了ステップが実行されます。これは、completion が呼び出され、フェーズ同期点でブロックされていたすべてのスレッドがブロック解除されることを意味します。完了ステップの終了は、完了ステップによってブロック解除されたすべての呼び出しが返るよりも強く先行 (strongly happens-before) します。
    期待カウントがゼロになった後、ちょうど一度だけ、あるスレッドが arrivearrive_and_drop、または wait の呼び出し中に完了ステップを実行します。ただし、どのスレッドも wait を呼び出さない場合にそのステップが実行されるかどうかは、実装定義です。
  3. 完了ステップが終了すると、期待カウントは構築時に指定された値から arrive_and_drop の呼び出し回数を引いた値にリセットされ、次のバリアフェーズが始まります。

barrier のメンバ関数(デストラクタを除く)を同時に呼び出しても、データ競合は発生しません。

目次

[編集] テンプレートパラメータ

CompletionFunction - 関数オブジェクト型
-
CompletionFunction は、MoveConstructible および Destructible の要件を満たさなければなりません。std::is_nothrow_invocable_v<CompletionFunction&>true でなければなりません。

CompletionFunction のデフォルトテンプレート引数は、DefaultConstructible の要件も満たす未規定の関数オブジェクト型です。その左辺値を引数なしで呼び出しても、何も効果はありません。

[編集] メンバ型

名前 定義
arrival_token MoveConstructibleMoveAssignableDestructible の要件を満たす未規定のオブジェクト型

[編集] データメンバ

メンバ 定義
CompletionFunction completion 各フェーズ完了ステップで呼び出される完了関数オブジェクト
(説明用のメンバオブジェクト*)

[編集] メンバ関数

barrier を構築する
(public member function) [編集]
barrier を破棄する
(public member function) [編集]
operator=
[削除]
barrier は代入不可
(public member function)
バリアに到達し、期待カウントをデクリメントする
(public member function) [編集]
フェーズ同期点で、そのフェーズ完了ステップが実行されるまでブロックする
(public member function) [編集]
バリアに到達して期待カウントを1つデクリメントし、現在のフェーズが完了するまでブロックする
(public member function) [編集]
後続のフェーズの初期期待カウントと現在のフェーズの期待カウントの両方を1つデクリメントする
(public member function) [編集]
定数
[static]
実装がサポートする期待カウントの最大値
(public static member function) [編集]

[編集] ノート

機能テストマクロ 規格 機能
__cpp_lib_barrier 201907L (C++20) std::barrier
202302L (C++20)
(DR)
フェーズ完了の保証を緩和

[編集]

#include <barrier>
#include <iostream>
#include <string>
#include <syncstream>
#include <thread>
#include <vector>
 
int main()
{
    const auto workers = {"Anil", "Busara", "Carl"};
 
    auto on_completion = []() noexcept
    {
        // locking not needed here
        static auto phase =
            "... done\n"
            "Cleaning up...\n";
        std::cout << phase;
        phase = "... done\n";
    };
 
    std::barrier sync_point(std::ssize(workers), on_completion);
 
    auto work = [&](std::string name)
    {
        std::string product = "  " + name + " worked\n";
        std::osyncstream(std::cout) << product;  // ok, op<< call is atomic
        sync_point.arrive_and_wait();
 
        product = "  " + name + " cleaned\n";
        std::osyncstream(std::cout) << product;
        sync_point.arrive_and_wait();
    };
 
    std::cout << "Starting...\n";
    std::vector<std::jthread> threads;
    threads.reserve(std::size(workers));
    for (auto const& worker : workers)
        threads.emplace_back(work, worker);
}

実行結果の例

Starting...
  Anil worked
  Carl worked
  Busara worked
... done
Cleaning up...
  Busara cleaned
  Carl cleaned
  Anil cleaned
... done

[編集] 欠陥報告

以下の動作変更を伴う欠陥報告が、以前に公開されたC++標準に遡って適用されました。

DR 適用対象 公開された動作 正しい動作
P2588R3 C++20 古いフェーズ完了保証がハードウェアアクセラレーションを妨げる可能性がある 緩和された

[編集] 関連項目

(C++20)
一度だけ使用可能なスレッドバリア
(クラス) [編集]
English 日本語 中文(简体) 中文(繁體)