Namensräume
Varianten
Aktionen

std::notify_all_at_thread_exit

Von cppreference.com
< cpp‎ | thread
 
 
Bibliothek für nebenläufige Programmierung
Threads
(C++11)
(C++20)
this_thread Namespace
(C++11)
(C++11)
(C++11)
Kooperatives Beenden
Gegenseitiger Ausschluss
(C++11)
Allgemeines Sperrungsmanagement
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
Bedingungsvariablen
notify_all_at_thread_exit
(C++11)
(C++11)
Semaphoren
Latches und Barriers
(C++20)
(C++20)
Futures
(C++11)
(C++11)
(C++11)
(C++11)
Sichere Wiederherstellung
(C++26)
Hazard Pointer
Atomare Typen
(C++11)
(C++20)
Initialisierung von atomaren Typen
(C++11)(veraltet in C++20)
(C++11)(veraltet in C++20)
Speicherordnung
(C++11)(deprecated in C++26)
Freie Funktionen für atomare Operationen
Freie Funktionen für atomare Flags
 
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_exit
synchronisiert 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>) [bearbeiten]
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...)>) [bearbeiten]