std::barrier

来自cppreference.com
< cpp‎ | thread
 
 
并发支持库
线程
(C++11)
(C++20)
(C++20)
this_thread 命名空间
(C++11)
(C++11)
(C++11)
原子类型
(C++11)
(C++20)
原子类型的初始化
(C++11)(C++20 中弃用)
(C++11)(C++20 中弃用)
原子操作的自由函数
原子标志的自由函数
内存序
互斥
(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)
 
 
在标头 <barrier> 定义
template<class CompletionFunction = /* see below */>
class barrier;
(C++20 起)

类模板 std::barrier 提供允许至多为期待数量的线程阻塞直至期待数量的线程到达该屏障。不同于 std::latch ,屏障可重用:一旦到达的线程从屏障阶段的同步点除阻,则可重用同一屏障。

屏障对象的生存期由屏障阶段的序列组成。每个阶段定义一个阶段同步点。在阶段中到达屏障的线程能通过调用 wait 在阶段同步点上阻塞,而且将保持阻塞直至运行阶段完成步骤。

屏障阶段由以下步骤组成:

  1. 每次调用 arrivearrive_and_drop 减少期待计数
  2. 期待计数抵达零时,运行阶段完成步骤。完成步骤调用完成函数对象,并除阻所有在阶段同步点上阻塞的线程。完成步骤的结束强先发生于所有从完成步骤所除阻的调用的返回。
    恰好在期待计数抵达零后,一个线程会在其调用 arrivearrive_and_dropwait 的过程中执行完成步骤,除了如果没有线程调用 wait 则是否执行完成步骤为实现定义。
  3. 完成步骤结束时,重置期待计数为构造中指定的值,可能为 arrive_and_drop 调用所调整,并开始下一阶段。

同时调用 barrier 的成员函数,除了析构函数,不引入数据竞争。

模板形参

CompletionFunction - 函数对象类型
-
CompletionFunction 必须符合可移动构造 (MoveConstructible) 可析构 (Destructible) 的要求。std::is_nothrow_invocable_v<CompletionFunction&> 必须为 true

CompletionFunction 的默认模板实参是未指定的函数对象类型,额外满足可默认构造 (DefaultConstructible) 的要求。以无参数调用其左值无效果。

每个屏障对象表现为如同它保有一个 CompletionFunction 类型的非静态数据成员 completion_ ,并在每个阶段完成步骤通过 completion_() 调用它。

成员类型

名称 定义
arrival_token 未指定的对象类型,符合可移动构造 (MoveConstructible) 可移动赋值 (MoveAssignable) 可析构 (Destructible) 的要求

成员函数

构造 barrier
(公开成员函数)
销毁 barrier
(公开成员函数)
operator=
[被删除]
barrier 不可赋值
(公开成员函数)
到达屏障并减少期待计数
(公开成员函数)
在阶段同步点阻塞,直至运行其阶段完成步骤
(公开成员函数)
到达屏障并把期待计数减少一,然后阻塞直至当前阶段完成
(公开成员函数)
将后继阶段的初始期待计数和当前阶段的期待计数均减少一
(公开成员函数)
常量
[静态]
实现所支持的期待计数的最大值
(公开静态成员函数)

注解

功能特性测试 标准 注释
__cpp_lib_barrier 201907L (C++20) std::barrier
202302L (C++20)
(DR)
放松的阶段完成保证

示例

#include <barrier>
#include <iostream>
#include <string>
#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::cout << product;  // ok, op<< call is atomic
    sync_point.arrive_and_wait();
 
    product = "  " + name + " cleaned\n";
    std::cout << product;
    sync_point.arrive_and_wait();
  };
 
  std::cout << "Starting...\n";
  std::vector<std::thread> threads;
  for (auto const& worker : workers) {
    threads.emplace_back(work, worker);
  }
  for (auto& thread : threads) {
    thread.join();
  }
}

可能的输出:

Starting...
  anil worked
  carl worked
  busara worked
... done
Cleaning up...
  busara cleaned
  carl cleaned
  anil cleaned
... done

缺陷报告

下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。

缺陷报告 应用于 出版时的行为 正确行为
P2588R3 C++20 旧的阶段完成保证可能阻碍硬件加速 已放松

参阅

(C++20)
单次使用的线程屏障
(类)