Spec-Zone.ru › C++

std::barrier

Определено в заголовке <barrier>
template< class CompletionFunction = /* see below */ >
class barrier;
(с C++20)

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

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

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

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

Конкурентные вызовы методов barrier, за исключением деструктора, не вводят гонки данных.

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

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

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

Каждый объект барьера ведет себя так, как будто он содержит единственный, нестатический член completion_ типа CompletionFunction и вызывает его по completion_() на каждом шаге завершения фазы.

Типы членов

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

Члены-функции

(конструктор)
создаёт 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/w/cpp/thread/barrier

Spec-Zone.ru

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