std:: call_once
|
Definiert in Header
<mutex>
|
||
|
template
<
class
Callable,
class
...
Args
>
void call_once ( std:: once_flag & flag, Callable && f, Args && ... args ) ; |
(seit C++11) | |
Führt das Callable Objekt f genau einmal aus, selbst wenn es gleichzeitig von mehreren Threads aufgerufen wird.
Im Detail:
-
Falls zum Zeitpunkt des Aufrufs von
std::call_onceder flag anzeigt, dass f bereits aufgerufen wurde, kehrtstd::call_oncesofort zurück (ein solcher Aufruf vonstd::call_oncewird als passiv bezeichnet).
-
Andernfalls ruft
std::call_onceINVOKE ( std:: forward < Callable > ( f ) , std:: forward < Args > ( args ) ... ) auf. Im Gegensatz zum std::thread -Konstruktor oder std::async werden die Argumente nicht verschoben oder kopiert, da sie nicht an einen anderen Ausführungs-Thread übertragen werden müssen (ein solcher Aufruf vonstd::call_oncewird als aktiv bezeichnet).
-
-
Wenn dieser Aufruf eine Exception wirft, wird sie an den Aufrufer von
std::call_onceweitergegeben, und das flag wird nicht umgeschaltet, sodass ein weiterer Aufruf versucht wird (ein solcher Aufruf vonstd::call_oncewird als exceptional bezeichnet). -
Wenn dieser Aufruf normal zurückkehrt (ein solcher Aufruf von
std::call_oncewird als returning bezeichnet), wird das flag umgeschaltet, und alle anderen Aufrufe vonstd::call_oncemit demselben flag sind garantiert passive .
-
Wenn dieser Aufruf eine Exception wirft, wird sie an den Aufrufer von
Alle aktiven Aufrufe auf derselben flag bilden eine einzige Gesamtordnung, bestehend aus null oder mehreren exceptional Aufrufen, gefolgt von einem returning Aufruf. Das Ende jedes aktiven Aufrufs synchronisiert sich mit dem nächsten aktiven Aufruf in dieser Ordnung.
Die Rückkehr vom
returning
Aufruf synchronisiert-sich mit den Rückkehren aller
passive
Aufrufe auf derselben
flag
: dies bedeutet, dass alle gleichzeitigen Aufrufe von
std::call_once
garantiert alle Nebeneffekte beobachten können, die durch den
active
Aufruf erzeugt wurden, ohne zusätzliche Synchronisation.
Inhaltsverzeichnis |
Parameter
| flag | - | ein Objekt, für das genau eine Funktion ausgeführt wird |
| f | - | Callable aufzurufendes Objekt |
| args... | - | an die Funktion zu übergebende Argumente |
Rückgabewert
(keine)
Ausnahmen
-
std::system_error
falls irgendeine Bedingung Aufrufe von
std::call_oncean der Ausführung gemäß Spezifikation hindert. - Jede Ausnahme, die von f geworfen wird.
Hinweise
Wenn gleichzeitige Aufrufe von
std::call_once
unterschiedliche Funktionen
f
übergeben, ist nicht spezifiziert, welche
f
aufgerufen wird. Die ausgewählte Funktion wird im selben Thread ausgeführt wie der
std::call_once
-Aufruf, an den sie übergeben wurde.
Die Initialisierung von
funktionslokalen Static-Variablen
ist garantiert nur einmalig, selbst wenn sie von mehreren Threads aufgerufen wird, und kann effizienter sein als der entsprechende Code mit
std::call_once
.
Das POSIX-Äquivalent dieser Funktion ist
pthread_once
.
Beispiel
#include <iostream> #include <mutex> #include <thread> std::once_flag flag1, flag2; void simple_do_once() { std::call_once(flag1, [](){ std::cout << "Simple example: called once\n"; }); } void may_throw_function(bool do_throw) { if (do_throw) { std::cout << "Throw: call_once will retry\n"; // dies kann mehrfach erscheinen throw std::exception(); } std::cout << "Did not throw, call_once will not attempt again\n"; // garantiert einmalig } void do_once(bool do_throw) { try { std::call_once(flag2, may_throw_function, do_throw); } catch (...) {} } int main() { std::thread st1(simple_do_once); std::thread st2(simple_do_once); std::thread st3(simple_do_once); std::thread st4(simple_do_once); st1.join(); st2.join(); st3.join(); st4.join(); std::thread t1(do_once, true); std::thread t2(do_once, true); std::thread t3(do_once, false); std::thread t4(do_once, true); t1.join(); t2.join(); t3.join(); t4.join(); }
Mögliche Ausgabe:
Simple example: called once Throw: call_once will retry Throw: call_once will retry Throw: call_once will retry Did not throw, call_once will not attempt again
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 |
|---|---|---|---|
| LWG 2080 | C++11 |
std::invalid_argument
würde ausgelöst, wenn
f
ungültig ist,
aber das Szenario, in dem f ungültig wird, ist nicht spezifiziert |
diesen Fehlerzustand entfernt |
| LWG 2442 | C++11 | die Argumente wurden vor dem Aufruf kopiert und/oder verschoben | kein Kopieren/Verschieben wird durchgeführt |
Siehe auch
|
(C++11)
|
Hilfsobjekt zur Sicherstellung, dass
call_once
die Funktion nur einmal aufruft
(Klasse) |
|
C-Dokumentation
für
call_once
|
|