std::notify_all_at_thread_exit
| Definiert im Header <condition_variable> |
||
| void notify_all_at_thread_exit( std::condition_variable& cond, std::unique_lock<std::mutex> lk ); |
(seit C++11) | |
notify_all_at_thread_exit bietet einen Mechanismus, um andere Threads zu benachrichtigen, dass ein bestimmter Thread vollständig beendet wurde, einschließlich der Zerstörung aller thread_local Objekte. Es funktioniert wie folgt:
- Der Besitz des zuvor erworbenen Locks lk wird in einen internen Speicher übertragen.
- Die Ausführungsumgebung wird so modifiziert, dass beim Beenden des aktuellen Threads die Bedingungsvariable cond benachrichtigt wird, als ob durch lk.unlock();
cond.notify_all();.
Das implizite lk.unlock() wird sequenziert nach der Zerstörung aller Objekte mit Thread-lokaler Speicherdauer, die mit dem aktuellen Thread assoziiert sind.
Wenn eine der folgenden Bedingungen erfüllt ist, ist das Verhalten undefiniert
- lk ist für den aufrufenden Thread nicht gesperrt.
- Wenn andere Threads ebenfalls auf cond warten, ist lk.mutex() anders als das Mutex, das von den Wartefunktionen (
wait, wait_for und wait_until) freigegeben wird, die auf cond von diesen Threads aufgerufen werden.
Inhalt |
[bearbeiten] Hinweise
Ein äquivalenter Effekt kann mit den von std::promise oder std::packaged_task bereitgestellten Einrichtungen erzielt werden.
Der bereitgestellte Lock lk wird gehalten, bis der Thread beendet wird. Sobald diese Funktion aufgerufen wurde, dürfen keine weiteren Threads denselben Lock erwerben, um auf cond zu warten. Wenn einige Threads auf diese Bedingungsvariable warten, stellen Sie sicher, dass die Bedingung, auf die gewartet wird, erfüllt ist, während Sie den Lock auf lk halten, und dass dieser Lock nicht freigegeben und erneut erworben wird, bevor notify_all_at_thread_exit aufgerufen wird, um Verwechslungen durch zufällige Aufweckungen in anderen Threads zu vermeiden.
In typischen Anwendungsfällen ist diese Funktion das Letzte, was von einem getrennten Thread aufgerufen wird.
[bearbeiten] Parameter
| cond | - | die Bedingungsvariable, die beim Beenden des Threads benachrichtigt werden soll |
| lk | - | der Lock, der mit der Bedingungsvariable cond verbunden ist |
[bearbeiten] Rückgabewert
(keine)
[bearbeiten] Beispiel
Dieser Codeausschnitt veranschaulicht, wie notify_all_at_thread_exit verwendet werden kann, um den Zugriff auf Daten zu vermeiden, die von Thread-lokalen Objekten abhängen, während diese Thread-lokalen Objekte gerade zerstört werden.
#include <cassert> #include <condition_variable> #include <mutex> #include <string> #include <thread> std::mutex m; std::condition_variable cv; bool ready = false; std::string result; // some arbitrary type void thread_func() { thread_local std::string thread_local_data = "42"; std::unique_lock<std::mutex> lk(m); // assign a value to result using thread_local data result = thread_local_data; ready = true; std::notify_all_at_thread_exit(cv, std::move(lk)); } // 1. destroy thread_locals; // 2. unlock mutex; // 3. notify cv. int main() { std::thread t(thread_func); t.detach(); // do other work // ... // wait for the detached thread std::unique_lock<std::mutex> lk(m); cv.wait(lk, []{ return ready; }); // result is ready and thread_local destructors have finished, no UB assert(result == "42"); }
[bearbeiten] Fehlerberichte
Die folgenden Verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.
| DR | angewendet auf | Verhalten wie veröffentlicht | Korrigiertes Verhalten |
|---|---|---|---|
| LWG 2140 | C++11 | der Aufruf von notify_all_at_thread_exitsynchronisiert mit Aufrufen von Funktionen, die auf cond warten |
die Synchronisation wurde aktualisiert Anforderung |
[bearbeiten] Siehe auch
| setzt das Ergebnis auf einen bestimmten Wert und liefert die Benachrichtigung erst beim Beenden des Threads (öffentliche Memberfunktion von std::promise<R>) | |
| führt die Funktion aus und stellt sicher, dass das Ergebnis erst bereit ist, wenn der aktuelle Thread beendet wurde (öffentliche Memberfunktion von std::packaged_task<R(Args...)>) |