std::barrier
来自 cppreference.com
定义在头文件 <barrier> 中 |
||
template< class CompletionFunction = /* see below */ > class barrier; |
(自 C++20 起) | |
类模板 std::barrier
提供了一个线程协调机制,该机制会阻塞一组已知大小的线程,直到该组中的所有线程都到达屏障。与 std::latch 不同,屏障是可重复使用的:一旦一组到达的线程被解阻塞,屏障就可以被重复使用。与 std::latch 不同,屏障在解阻塞线程之前会执行一个可能为空的可调用对象。
屏障对象的生存期包含一个或多个阶段。每个阶段都定义了一个阶段同步点,在那里等待的线程会阻塞。线程可以到达屏障,但可以通过调用 arrive
延迟在阶段同步点上的等待。这些线程随后可以通过调用 wait
在阶段同步点上阻塞。
屏障阶段包含以下步骤
- 每次调用
arrive
或arrive_and_drop
都会使预期计数递减。 - 当预期计数达到零时,阶段完成步骤会运行,这意味着
completion
会被调用,并且在阶段同步点上阻塞的所有线程都会被解阻塞。完成步骤的结束 严格地发生在 所有被完成步骤解阻塞的调用返回之前。
在预期计数达到零之后,只有一次,线程会在其对arrive
、arrive_and_drop
或wait
的调用期间执行完成步骤,但如果没有任何线程调用wait
,则步骤是否执行是实现定义的。 - 完成步骤完成后,预期计数将重置为构造时指定的 value 值,减去自上次调用
arrive_and_drop
以来调用次数,并且下一个屏障阶段开始。
barrier
的成员函数的并发调用不会引入数据竞争,除了析构函数。
内容 |
[编辑] 模板参数
CompletionFunction | - | 一个函数对象类型 |
-CompletionFunction 必须满足 MoveConstructible 和 Destructible 的要求。 std::is_nothrow_invocable_v<CompletionFunction&> 必须为 true。 |
CompletionFunction
的默认模板参数是一个未指定的函数对象类型,它还满足 DefaultConstructible 的要求。调用它不带参数的左值没有任何效果。
[编辑] 成员类型
名称 | 定义 |
arrival_token
|
一个未指定的对象类型,满足 MoveConstructible、MoveAssignable 和 Destructible 的要求 |
[编辑] 数据成员
成员 | 定义 |
CompletionFunction completion |
一个完成函数对象,在每个阶段完成步骤中都会被调用 (仅用于说明目的的成员对象*) |
[编辑] 成员函数
构造一个 barrier (公共成员函数) | |
销毁 barrier (公共成员函数) | |
运算符= [已删除] |
barrier 不可赋值(公共成员函数) |
到达屏障并递减预期计数 (公共成员函数) | |
在阶段同步点阻塞,直到其阶段完成步骤运行 (公共成员函数) | |
到达屏障并递减预期计数,然后阻塞直到当前阶段完成 (公共成员函数) | |
递减后续阶段的初始预期计数和当前阶段的预期计数 (公共成员函数) | |
常量 | |
[静态] |
实现支持的预期计数的最大值 (公共静态成员函数) |
[编辑] 备注
特性测试 宏 | 值 | Std | 特性 |
---|---|---|---|
__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) |
一次性线程屏障 (类) |