Namensräume
Varianten
Aktionen

std::condition_variable_any::wait

Von cppreference.com
 
 
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
(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
 
 
template< class Lock >
void wait( Lock& lock );
(1) (seit C++11)
template< class Lock, class Predicate >
void wait( Lock& lock, Predicate pred );
(2) (seit C++11)
template< class Lock, class Predicate >
bool wait( Lock& lock, std::stop_token stoken, Predicate pred );
(3) (seit C++20)

wait bewirkt, dass der aktuelle Thread blockiert wird, bis die Bedingungsvariable benachrichtigt wird oder ein sporadischer Aufwachvorgang eintritt. pred kann optional angegeben werden, um sporadische Aufwachvorgänge zu erkennen.

1) Ruft atomar lock.unlock() auf und blockiert auf *this.
Der Thread wird entblockiert, wenn notify_all() oder notify_one() ausgeführt wird. Er kann auch sporadisch entblockiert werden.
Wenn entsperrt, ruft lock.lock() auf (möglicherweise blockierend auf dem Lock) und gibt dann zurück.
2,3) Warten auf eine bestimmte Bedingung, die wahr wird, kann verwendet werden, um sporadische Erweckungen zu ignorieren.
2) Äquivalent zu
while (!pred())
    wait(lock);
3) Registriert *this für die Dauer dieses Aufrufs, um benachrichtigt zu werden, wenn eine Stoppanforderung für stokens zugehöriger Stoppzustand gemacht wird; dies ist dann äquivalent zu
while (!stoken.stop_requested())
{
    if (pred())
        return true;
    wait(lock);
}
return pred();

Direkt nach der Rückgabe von wait wird lock vom aufrufenden Thread gesperrt. Wenn diese Nachbedingung nicht erfüllt werden kann[1], wird std::terminate aufgerufen.

  1. Dies kann passieren, wenn das erneute Sperren des Mutex eine Ausnahme auslöst.

Inhalt

[edit] Parameter

lock - ein Lock, der vom aufrufenden Thread gesperrt sein muss
stoken - ein Stop-Token, um die Unterbrechung dafür zu registrieren
pred - das Prädikat, um zu überprüfen, ob das Warten abgeschlossen werden kann
Typanforderungen
-
Lock muss die Anforderungen von BasicLockable erfüllen.
-
Predicate muss die Anforderungen an ein FunctionObject erfüllen.
-
pred() muss ein gültiger Ausdruck sein, und sein Typ und seine Wertkategorie müssen die BooleanTestable-Anforderungen erfüllen.

[edit] Rückgabewert

1,2) (keine)
3) Das letzte Ergebnis von pred() vor der Rückgabe an den Aufrufer.

[edit] Ausnahmen

1) Wirft keine Ausnahmen.
2,3) Jegliche Ausnahme, die von pred geworfen wird.

[edit] Hinweise

Der Rückgabewert von Überladung (3) gibt an, ob pred zu true ausgewertet wurde, unabhängig davon, ob eine Stoppanforderung gestellt wurde oder nicht.

Die Effekte von notify_one()/notify_all() und jeder der drei atomaren Teile von wait()/wait_for()/wait_until() (entsperren+warten, aufwecken und sperren) finden in einer einzigen Gesamtordnung statt, die als Modifikationsordnung einer atomaren Variablen betrachtet werden kann: Die Ordnung ist spezifisch für diese einzelne Bedingungsvariable. Dies macht es unmöglich, dass notify_one() beispielsweise verzögert wird und einen Thread aufweckt, der kurz nach dem Aufruf von notify_one() zu warten begonnen hat.

[edit] Beispiel

#include <chrono>
#include <condition_variable>
#include <iostream>
#include <thread>
 
std::condition_variable_any cv;
std::mutex cv_m; // This mutex is used for three purposes:
                 // 1) to synchronize accesses to i
                 // 2) to synchronize accesses to std::cerr
                 // 3) for the condition variable cv
int i = 0;
 
void waits()
{
    std::unique_lock<std::mutex> lk(cv_m);
    std::cerr << "Waiting... \n";
    cv.wait(lk, []{ return i == 1; });
    std::cerr << "...finished waiting. i == 1\n";
}
 
void signals()
{
    std::this_thread::sleep_for(std::chrono::seconds(1));
    {
        std::lock_guard<std::mutex> lk(cv_m);
        std::cerr << "Notifying...\n";
    }
    cv.notify_all();
 
    std::this_thread::sleep_for(std::chrono::seconds(1));
 
    {
        std::lock_guard<std::mutex> lk(cv_m);
        i = 1;
        std::cerr << "Notifying again...\n";
    }
    cv.notify_all();
}
 
int main()
{
    std::thread t1(waits), t2(waits), t3(waits), t4(signals);
    t1.join(); 
    t2.join(); 
    t3.join();
    t4.join();
}

Mögliche Ausgabe

Waiting...
Waiting...
Waiting...
Notifying...
Notifying again...
...finished waiting. i == 1
...finished waiting. i == 1
...finished waiting. i == 1

[edit] 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 2114
(P2167R3)
C++11 Konvertierbarkeit in bool war zu schwach, um die Erwartungen der Implementierungen widerzuspiegeln Anforderungen verstärkt
LWG 2135 C++11 Das Verhalten war unklar, wenn lock.lock() eine Ausnahme auslöste in diesem Fall wird std::terminate aufgerufen

[edit] Siehe auch

blockiert den aktuellen Thread, bis die Bedingungsvariable geweckt wird oder nach Ablauf der angegebenen Timeout-Dauer
(public member function) [bearbeiten]
blockiert den aktuellen Thread, bis die Bedingungsvariable geweckt wird oder bis der angegebene Zeitpunkt erreicht ist
(public member function) [bearbeiten]
C-Dokumentation für cnd_wait

[edit] Externe Links

Artikel "The Old New Thing": Spurious wake-ups in Win32 condition variables.