std::barrier
Определено в заголовке <barrier> | ||
|---|---|---|
template< class CompletionFunction = /* see below */ > class barrier; | (с C++20) |
Шаблон класса std::barrier предоставляет механизм координации потоков, который блокирует группу потоков известного размера до тех пор, пока все потоки в этой группе не достигнут барьера. В отличие от std::latch, барьеры являются многоразовыми: после разблокирования группы прибывающих потоков, барьер может быть повторно использован. В отличие от std::latch, барьеры выполняют, возможно, пустую вызываемую функцию перед разблокировкой потоков.
Жизненный цикл объекта барьера состоит из одной или нескольких фаз. Каждая фаза определяет точку синхронизации фазы, где ожидают потоки. Потоки могут прибыть к барьеру, но отложить ожидание в точке синхронизации фазы, вызвав arrive. Такие потоки могут позже заблокироваться на точке синхронизации фазы, вызвав wait.
Фаза барьера состоит из следующих шагов:
- Ожидаемое количество уменьшается при каждом вызове
arriveилиarrive_and_drop. - Когда ожидаемое количество достигает нуля, выполняется шаг завершения фазы, что означает, что вызывается
CompletionFunction, и все потоки, заблокированные в точке синхронизации фазы, разблокируются. Конец шага завершения строго предшествует всем вызовам, которые были разблокированы шагом завершения, возвращаются.
Точно один раз после того, как ожидаемое количество достигнет нуля, поток выполняет шаг завершения во время своего вызоваarrive,arrive_and_dropилиwait, за исключением того, что определяется реализацией, выполняется ли шаг, если ни один поток не вызываетwait. - Когда шаг завершения завершен, ожидаемое количество сбрасывается до значения, указанного при создании, минус количество вызовов
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 нельзя присваивать (публичный член-функция) |
| прибывает к барьеру и уменьшает ожидаемое количество (публичный член-функция) |
|
| блокируется в точке синхронизации фазы до тех пор, пока не будет выполнена её фаза завершения (публичный член-функция) |
|
| прибывает к барьеру и уменьшает ожидаемое количество на единицу, затем блокируется до завершения текущей фазы (публичный член-функция) |
|
| уменьшает начальное ожидаемое количество для последующих фаз и ожидаемое количество для текущей фазы на единицу (публичный член-функция) |
|
Константы |
|
|
[статический] | максимальное значение ожидаемого количества, поддерживаемое реализацией (публичный статический член-функция) |
Примечания
| Макросы проверки возможностей | Значение | Стандарт | Возможность |
|---|---|---|---|
__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) | барьер потоков однократного использования (класс) |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/thread/barrier