Spec-Zone.ru › C++

std::barrier

Определён в заголовочном файле <barrier>
template< class CompletionFunction = /* see below */ >
class barrier;
(начиная с C++20)

Шаблон класса std::barrier предоставляет механизм координации потоков, который блокирует группу потоков известного размера, пока все потоки в этой группе не достигнут барьера. В отличие от std::latch, барьеры можно использовать повторно: когда группа прибывших потоков разблокирована, барьер можно использовать снова. В отличие от std::latch, барьеры перед разблокировкой потоков выполняют возможно пустой вызываемый объект.

Время жизни объекта barrier состоит из одной или нескольких фаз. Каждая фаза определяет точку синхронизации фазы, в которой ожидающие потоки блокируются. Потоки могут прибыть к барьеру, отложив ожидание на точке синхронизации фазы вызовом arrive. Такие потоки могут позднее заблокироваться на точке синхронизации фазы, вызвав wait.

Фаза barrier состоит из следующих шагов:

  1. Ожидаемое количество уменьшается при каждом вызове arrive или arrive_and_drop.
  2. Когда ожидаемое количество достигает нуля, выполняется шаг завершения фазы: вызывается completion, и все потоки, заблокированные на точке синхронизации фазы, разблокируются. Завершение шага завершения строго предшествует возврату всех вызовов, разблокированных этим шагом.
    Ровно один раз после достижения ожидаемым количеством нуля поток выполняет шаг завершения в ходе вызова arrive, arrive_and_drop или wait. Исключение: если ни один поток не вызывает wait, выполнение этого шага определяется реализацией.
  3. По завершении шага завершения ожидаемое количество сбрасывается до значения, заданного при создании, за вычетом числа вызовов arrive_and_drop с момента этого сброса; начинается следующая фаза барьера.

Параллельные вызовы функций-членов barrier, за исключением деструктора, не приводят к гонкам данных.

Параметры шаблона

CompletionFunction - тип функционального объекта
-CompletionFunction должен соответствовать требованиям MoveConstructible и Destructible. std::is_nothrow_invocable_v<CompletionFunction&> должен быть true.

Аргумент шаблона по умолчанию для CompletionFunction — неуказанный тип функционального объекта, который также соответствует требованиям DefaultConstructible. Вызов его lvalue без аргументов не имеет эффектов.

Типы-члены

Имя Определение
arrival_token неуказанный тип объекта, соответствующий требованиям MoveConstructible, MoveAssignable и Destructible

Поля данных

Член Определение
CompletionFunction completion функциональный объект завершения, вызываемый при каждом шаге завершения фазы
(объект-член только для описания*)

Функции-члены

(конструктор)
создаёт barrier
(открытая функция-член)
(деструктор)
уничтожает barrier
(открытая функция-член)
operator=
[удалён]
barrier не поддерживает присваивание
(открытая функция-член)
arrive
прибывает к барьеру и уменьшает ожидаемое количество
(открытая функция-член)
wait
блокируется в точке синхронизации фазы до выполнения шага завершения этой фазы
(открытая функция-член)
arrive_and_wait
прибывает к барьеру, уменьшает ожидаемое количество на единицу, а затем блокируется до завершения текущей фазы
(открытая функция-член)
arrive_and_drop
уменьшает на единицу начальное ожидаемое количество для последующих фаз и ожидаемое количество для текущей фазы
(открытая функция-член)
Константы
max
[статический]
максимальное поддерживаемое реализацией значение ожидаемого количества
(открытая статическая функция-член)

Примечания

Макрос проверки поддержки функции Значение Стандарт Функция
__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 прежние гарантии завершения фазы могли препятствовать аппаратному ускорению ослаблены

См. также

latch
(C++20)
одноразовый барьер для потоков
(класс)

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/thread/barrier

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API