std::barrier
来自 cppreference.cn
定义于头文件 <barrier> |
||
template< class CompletionFunction = /* 见下方 */ > class barrier; |
(自 C++20 起) | |
类模板 std::barrier
提供了一种线程协调机制,它会阻塞已知大小的一组线程,直到该组中的所有线程都到达屏障。与 std::latch 不同,屏障是可重用的:一旦一组到达的线程被解除阻塞,屏障就可以被重用。与 std::latch 不同,屏障在解除阻塞线程之前执行一个可能为空的可调用对象。
一个屏障对象的生命周期由一个或多个阶段组成。每个阶段定义一个阶段同步点,等待线程在此处阻塞。线程可以到达屏障,但可以通过调用 arrive
来延迟等待阶段同步点。这些线程稍后可以通过调用 wait
在阶段同步点上阻塞。
一个屏障阶段包含以下步骤
- 预期计数会因每次调用
arrive
或arrive_and_drop
而递减。 - 当预期计数达到零时,阶段完成步骤会运行,这意味着
completion
被调用,并且所有在阶段同步点被阻塞的线程都被解除阻塞。完成步骤的结束 强先于 所有被完成步骤解除阻塞的调用的返回。
在预期计数达到零后,线程会在其对arrive
、arrive_and_drop
或wait
的调用期间精确地执行一次完成步骤,除非在没有线程调用wait
的情况下是否执行该步骤是实现定义的。 - 当完成步骤结束时,预期计数会被重置为构造时指定的值,减去自那时起调用
arrive_and_drop
的次数,并且下一个屏障阶段开始。
并发调用 barrier
的成员函数(析构函数除外)不会引入数据竞争。
目录 |
[编辑] 模板形参
CompletionFunction | - | 一个函数对象类型 |
-CompletionFunction 必须满足 可移动构造 和 可析构 的要求。 std::is_nothrow_invocable_v<CompletionFunction&> 必须为 true。 |
CompletionFunction
的默认模板实参是一个未指定的函数对象类型,它额外满足 默认可构造 的要求。使用无参数的左值调用它没有效果。
[编辑] 成员类型
名称 | 定义 |
arrival_token
|
一个未指定的对象类型,满足 可移动构造、可移动赋值 和 可析构 的要求 |
[编辑] 数据成员
成员 | 定义 |
CompletionFunction completion |
一个完成函数对象,在每个阶段完成步骤中被调用 (仅为说明目的的成员对象*) |
[编辑] 成员函数
构造一个 barrier (公有成员函数) | |
销毁 barrier (公有成员函数) | |
operator= [已删除] |
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) |
单次使用线程屏障 (类) |