Namensräume
Varianten
Aktionen

std::condition_variable::wait_for

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 Rep, class Period >

std::cv_status wait_for( std::unique_lock<std::mutex>& lock,

                         const std::chrono::duration<Rep, Period>& rel_time );
(1) (seit C++11)
template< class Rep, class Period, class Predicate >

bool wait_for( std::unique_lock<std::mutex>& lock,
               const std::chrono::duration<Rep, Period>& rel_time,

               Predicate pred );
(2) (seit C++11)

wait_for bewirkt, dass der aktuelle Thread blockiert, bis das condition_variable benachrichtigt wird, die gegebene Dauer abgelaufen ist oder ein fehlerhaftes Aufwachen (spurious wakeup) auftritt. pred kann optional angegeben werden, um fehlerhafte Aufwachvorgänge zu erkennen.

1) Äquivalent zu return wait_until(lock, std::chrono::steady_clock::now() + rel_time);.
2) Äquivalent zu return wait_until(lock, std::chrono::steady_clock::now() + rel_time, std::move(pred));.
Diese Überladung kann verwendet werden, um fehlerhafte Aufwachvorgänge zu ignorieren, während auf die Erfüllung einer bestimmten Bedingung gewartet wird.

Direkt nach Rückkehr von wait_for ist lock.owns_lock() true und lock.mutex() ist vom aufrufenden Thread gesperrt. Wenn diese Nachbedingungen nicht erfüllt werden können[1], wird std::terminate aufgerufen.

Wenn eine der folgenden Bedingungen erfüllt ist, ist das Verhalten undefiniert

  • lock.owns_lock() ist false.
  • lock.mutex() ist nicht vom aufrufenden Thread gesperrt.
  • Wenn andere Threads auf *this warten, ist lock.mutex() unterschiedlich von dem Mutex, der von den Wartefunktionen (wait, wait_for und wait_until) freigegeben wird, die auf *this von diesen Threads aufgerufen werden.
  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.
rel_time - Die maximale Wartezeit.
pred - das Prädikat, um zu überprüfen, ob das Warten abgeschlossen werden kann
Typanforderungen
-
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) std::cv_status::timeout, wenn rel_time seit Beginn dieses Aufrufs abgelaufen ist, andernfalls std::cv_status::no_timeout.
2) Das letzte Ergebnis von pred() vor der Rückgabe an den Aufrufer.

[edit] Ausnahmen

1) Zeitlimitbezogene Ausnahmen.
2) Zeitbezogene Ausnahmen und jede Ausnahme, die von pred ausgelöst wird.

[edit] Hinweise

Auch wenn unter dem Lock benachrichtigt wird, macht Überladung (1) keine Garantie bezüglich des Zustands des zugehörigen Prädikats beim Zurückkehren wegen Zeitablaufs.

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 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] Defect reports

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 2093 C++11 timeoutbezogene Ausnahmen fehlten in der Spezifikation erwähnt diese Ausnahmen
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
(public member function) [bearbeiten]
blockiert den aktuellen Thread, bis die Bedingungsvariable geweckt wird oder bis der angegebene Zeitpunkt erreicht ist
(public member function) [bearbeiten]