std:: barrier
|
Definiert in Header
<barrier>
|
||
|
template
<
class
CompletionFunction
=
/* siehe unten */
>
class barrier ; |
(seit C++20) | |
Die Klassenvorlage
std::barrier
bietet einen Thread-Koordinationsmechanismus, der eine Gruppe von Threads bekannter Größe blockiert, bis alle Threads in dieser Gruppe die Barriere erreicht haben. Im Gegensatz zu
std::latch
sind Barrieren wiederverwendbar: Sobald eine Gruppe ankommender Threads freigegeben wird, kann die Barriere erneut verwendet werden. Im Gegensatz zu
std::latch
führen Barrieren ein möglicherweise leeres Aufrufbares aus, bevor Threads freigegeben werden.
Die Lebensdauer eines Barrierenobjekts besteht aus einer oder mehreren Phasen. Jede Phase definiert einen
Phasen-Synchronisationspunkt
, an dem wartende Threads blockieren. Threads können an der Barriere ankommen, aber das Warten am
Phasen-Synchronisationspunkt
verzögern, indem sie
arrive
aufrufen. Solche Threads können später am
Phasen-Synchronisationspunkt
blockieren, indem sie
wait
aufrufen.
Eine Barriere phase besteht aus den folgenden Schritten:
-
Der
erwartete Zähler
wird durch jeden Aufruf von
arriveoderarrive_and_dropdekrementiert. -
Wenn der erwartete Zähler Null erreicht, wird der
Phasenabschlussschritt
ausgeführt, was bedeutet, dass die
completionaufgerufen wird und alle Threads, die am Phasen-Synchronisationspunkt blockiert sind, entblockt werden. Das Ende des Abschlussschritts strongly happens-before allen Aufrufen, die durch den Abschlussschritt entblockt wurden, zurückkehren.
Genau einmal, nachdem der erwartete Zähler Null erreicht hat, führt ein Thread den Abschlussschritt während seines Aufrufs vonarrive,arrive_and_dropoderwaitaus, außer dass implementierungsdefiniert ist, ob der Schritt ausgeführt wird, wenn kein Threadwaitaufruft. -
Wenn der Abschlussschritt beendet ist, wird der erwartete Zähler auf den bei der Konstruktion angegebenen Wert abzüglich der Anzahl der Aufrufe von
arrive_and_dropseitdem zurückgesetzt, und die nächste Barrierephase beginnt.
Gleichzeitige Aufrufe der Memberfunktionen von
barrier
, mit Ausnahme des Destruktors, führen nicht zu Datenrennen.
Inhaltsverzeichnis |
Template-Parameter
| CompletionFunction | - | ein Funktionsobjekttyp |
-
CompletionFunction
muss die Anforderungen von
MoveConstructible
und
Destructible
erfüllen.
std::
is_nothrow_invocable_v
<
CompletionFunction
&
>
muss
true
sein.
|
||
Das Standard-Template-Argument von
CompletionFunction
ist ein nicht näher spezifizierter Funktionsobjekttyp, der zusätzlich die Anforderungen von
DefaultConstructible
erfüllt. Der Aufruf eines Lvalues davon ohne Argumente hat keine Effekte.
Mitgliedertypen
| Name | Definition |
arrival_token
|
ein nicht näher bezeichneter Objekttyp, der die Anforderungen von MoveConstructible , MoveAssignable und Destructible erfüllt |
Datenmitglieder
| Member | Definition |
CompletionFunction
completion
|
ein Completion-Funktionsobjekt, das bei jedem Phasenabschlussschritt aufgerufen wird
( Nur zur Darstellung verwendetes Mitgliedsobjekt* ) |
Memberfunktionen
konstruiert eine
barrier
(öffentliche Elementfunktion) |
|
zerstört die
barrier
(öffentliche Elementfunktion) |
|
|
operator=
[deleted]
|
barrier
ist nicht zuweisbar
(öffentliche Elementfunktion) |
|
erreicht die Barriere und dekrementiert die erwartete Anzahl
(öffentliche Elementfunktion) |
|
|
blockiert am Phasen-Synchronisationspunkt bis ihr Phasenabschlussschritt ausgeführt wird
(öffentliche Elementfunktion) |
|
|
erreicht die Barriere und dekrementiert die erwartete Anzahl um eins, blockiert dann bis die aktuelle Phase abgeschlossen ist
(öffentliche Elementfunktion) |
|
|
dekrementiert sowohl die anfängliche erwartete Anzahl für nachfolgende Phasen als auch die erwartete Anzahl für die aktuelle Phase um eins
(öffentliche Elementfunktion) |
|
Konstanten |
|
|
[static]
|
der maximale Wert der erwarteten Anzahl, der von der Implementierung unterstützt wird
(öffentliche statische Elementfunktion) |
Hinweise
| Feature-Test Makro | Wert | Std | Feature |
|---|---|---|---|
__cpp_lib_barrier
|
201907L
|
(C++20) |
std::barrier
|
202302L
|
(C++20)
(DR) |
Gelockerte Garantien für Phasenabschluss |
Beispiel
#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); }
Mögliche Ausgabe:
Starting... Anil worked Carl worked Busara worked ... done Cleaning up... Busara cleaned Carl cleaned Anil cleaned ... done
Fehlerberichte
Die folgenden verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.
| DR | Angewendet auf | Verhalten wie veröffentlicht | Korrektes Verhalten |
|---|---|---|---|
| P2588R3 | C++20 | alte Phasenabschlussgarantien könnten Hardwarebeschleunigung verhindern | gelockert |
Siehe auch
|
(C++20)
|
Einmalige Thread-Barriere
(Klasse) |