std::condition_variable::wait_until
| template< class Clock, class Duration > std::cv_status |
(1) | (seit C++11) |
| template< class Clock, class Duration, class Predicate > bool wait_until( std::unique_lock<std::mutex>& lock, |
(2) | (seit C++11) |
wait_until veranlasst den aktuellen Thread, bis die Bedingungsvariable benachrichtigt wird, der angegebene Zeitpunkt erreicht ist oder ein falsches Erwachen auftritt, zu blockieren. pred kann optional zur Erkennung von falschen Erwachen bereitgestellt werden.
if (wait_until(lock, abs_time) == std::cv_status::timeout)
return pred();
return true;.
Unmittelbar nach der Rückgabe von wait_until ist lock.owns_lock() true, und lock.mutex() ist durch den 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 ebenfalls auf *this warten, unterscheidet sich lock.mutex() von dem Mutex, der durch die Wartefunktionen (wait, wait_for und
wait_until) auf *this durch diese Threads aufgerufen wird.
- ↑ 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 |
| abs_time | - | der Zeitpunkt, zu dem das Warten abläuft |
| 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
[edit] Ausnahmen
[edit] Hinweise
Der Standard empfiehlt, dass die mit abs_time verknüpfte Uhr zur Zeitmessung verwendet wird; diese Uhr muss keine monotone Uhr sein. Es gibt keine Garantien bezüglich des Verhaltens dieser Funktion, wenn die Uhr diskontinuierlich angepasst wird, aber die bestehenden Implementierungen konvertieren abs_time von Clock in std::chrono::system_clock und delegieren an POSIX pthread_cond_timedwait, so dass die Wartezeit Anpassungen der Systemuhr berücksichtigt, aber nicht die vom Benutzer bereitgestellte Clock. In jedem Fall kann die Funktion aufgrund von Zeitplanungs- oder Ressourcenkonfliktverzögerungen auch länger als bis nach dem Erreichen von abs_time warten.
Selbst wenn die verwendete Uhr std::chrono::steady_clock oder eine andere monotone Uhr ist, kann eine Anpassung der Systemuhr zu einem fehlerhaften Erwachen führen.
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] 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 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) | |
| blockiert den aktuellen Thread, bis die Bedingungsvariable geweckt wird oder nach Ablauf der angegebenen Timeout-Dauer (public member function) |