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
bewirkt, dass der aktuelle Thread blockiert, bis die Bedingungsvariable benachrichtigt wird, der angegebene Zeitpunkt erreicht wurde oder ein spontanes Aufwachen auftritt.
pred
kann optional bereitgestellt werden, um spontanes Aufwachen zu erkennen.
if ( wait_until ( lock, abs_time ) == std:: cv_status :: timeout )
return pred ( ) ;
return true ; .
Unmittelbar nachdem
wait_until
zurückkehrt, ist
lock.
owns_lock
(
)
true
, und
lock.
mutex
(
)
wird vom aufrufenden Thread gesperrt. Wenn diese Nachbedingungen nicht erfüllt werden können
[1]
, ruft die Funktion
std::terminate
auf.
Wenn eine der folgenden Bedingungen erfüllt ist, ist das Verhalten undefiniert:
- lock. owns_lock ( ) ist false .
- lock. mutex ( ) ist nicht durch den aufrufenden Thread gesperrt.
-
Falls andere Threads ebenfalls auf
*
this
warten,
lock.
mutex
(
)
unterscheidet sich vom Mutex, der durch die Wartefunktionen (
wait
,
wait_for
und
wait_until) auf * this durch jene Threads entsperrt wird.
- ↑ Dies kann passieren, wenn das erneute Sperren des Mutex eine Exception auslöst.
Inhaltsverzeichnis |
Parameter
| lock | - | eine Sperre, die vom aufrufenden Thread gesperrt werden muss |
| abs_time | - | der Zeitpunkt, an dem das Warten abläuft |
| pred | - | das Prädikat zur Überprüfung, ob das Warten abgeschlossen werden kann |
| Typanforderungen | ||
-
Predicate
muss die Anforderungen von
FunctionObject
erfüllen.
|
||
|
-
|
||
Rückgabewert
Ausnahmen
Hinweise
Der Standard empfiehlt, dass die an
abs_time
gebundene Uhr zur Zeitmessung verwendet wird; diese Uhr muss kein monotones Zeitgeber 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
zu
std::chrono::system_clock
und delegieren an POSIX
pthread_cond_timedwait
, sodass das Warten Anpassungen der Systemuhr berücksichtigt, nicht jedoch die benutzerbereitgestellte
Clock
. In jedem Fall kann die Funktion auch länger warten, als bis
abs_time
erreicht wurde, aufgrund von Planungs- oder Ressourcenkonfliktverzögerungen.
Selbst wenn die verwendete Uhr std::chrono::steady_clock oder eine andere monotone Uhr ist, kann eine Systemzeitanpassung einen falschen Wakeup auslösen.
Die Effekte von
notify_one()
/
notify_all()
und jeder der drei atomaren Bestandteile von
wait()
/
wait_for()
/
wait_until()
(Entsperren+Warten, Aufwecken und Sperren) finden in einer einzigen Gesamtordnung statt, die als
Modifikationsreihenfolge
einer atomaren Variable betrachtet werden kann: Die Reihenfolge ist spezifisch für diese individuelle Bedingungsvariable. Dies macht es unmöglich, dass
notify_one()
beispielsweise verzögert wird und einen Thread entsperrt, der erst nach dem Aufruf von
notify_one()
mit dem Warten begonnen hat.
Beispiel
#include <chrono> #include <condition_variable> #include <iostream> #include <thread> std::condition_variable cv; std::mutex cv_m; // Dieses Mutex wird für drei Zwecke verwendet: // 1) zum Synchronisieren von Zugriffen auf i // 2) zum Synchronisieren von Zugriffen auf std::cerr // 3) für die 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
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 | timeout-bezogene Ausnahmen fehlten in der Spezifikation | erwähnt diese Ausnahmen |
|
LWG 2114
( P2167R3 ) |
C++11 | Konvertierbarkeit zu 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 wirft | ruft std::terminate in diesem Fall auf |
Siehe auch
|
blockiert den aktuellen Thread, bis die Condition Variable aufgeweckt wird
(öffentliche Elementfunktion) |
|
|
blockiert den aktuellen Thread, bis die Condition Variable aufgeweckt wird oder nach Ablauf der angegebenen Timeout-Dauer
(öffentliche Elementfunktion) |