Namespaces
Variants

std::condition_variable_any:: wait_until

From cppreference.net
Concurrency support library
Threads
(C++11)
(C++20)
this_thread namespace
(C++11)
(C++11)
Cooperative cancellation
Mutual exclusion
Generic lock management
Condition variables
(C++11)
Semaphores
Latches and Barriers
(C++20)
(C++20)
Futures
(C++11)
(C++11)
(C++11)
Safe reclamation
Hazard pointers
Atomic types
(C++11)
(C++20)
Initialization of atomic types
(C++11) (deprecated in C++20)
(C++11) (deprecated in C++20)
Memory ordering
(C++11) (deprecated in C++26)
Free functions for atomic operations
Free functions for atomic flags
template < class Lock, class Clock, class Duration >

std:: cv_status
wait_until ( Lock & lock,

const std:: chrono :: time_point < Clock, Duration > & abs_time ) ;
(1) (seit C++11)
template < class Lock, class Clock, class Duration, class Predicate >

bool wait_until ( Lock & lock,
const std:: chrono :: time_point < Clock, Duration > & abs_time,

Predicate pred ) ;
(2) (seit C++11)
template < class Lock, class Clock, class Duration, class Predicate >

bool wait_until ( Lock & lock, std:: stop_token stoken,
const std:: chrono :: time_point < Clock, Duration > & abs_time,

Predicate pred ) ;
(3) (seit C++20)

wait_until bewirkt, dass der aktuelle Thread blockiert, bis die Bedingungsvariable benachrichtigt wird, die angegebene Dauer abgelaufen ist oder ein spontanes Aufwachen auftritt. pred kann optional bereitgestellt werden, um spontanes Aufwachen zu erkennen.

1) Ruft atomar lock. unlock ( ) auf und blockiert auf * this .
Der Thread wird entblockt, wenn notify_all() oder notify_one() ausgeführt wird, oder wenn abs_time erreicht ist. Es kann auch sporadisch ohne Grund entblockt werden.
Wenn freigegeben, ruft es lock. lock ( ) (möglicherweise blockierend auf die Sperre) und kehrt dann zurück.
2,3) Warten auf das Eintreten einer bestimmten Bedingung, kann verwendet werden, um falsche Aufweckvorgänge zu ignorieren.
2) Entspricht while ( ! pred ( ) )
if ( wait_until ( lock, abs_time ) == std:: cv_status :: timeout )
return pred ( ) ;
return true ;
.
3) Registriert * this für die Dauer dieses Aufrufs, um benachrichtigt zu werden, falls eine Stoppanforderung für den zugehörigen Stoppzustand von stoken gestellt wird; es entspricht dann while ( ! stoken. stop_requested ( ) )
{
if ( pred ( ) )
return true ;
if ( wait_until ( lock, abs_time ) == std:: cv_status :: timeout )
return pred ( ) ;
}
return pred ( ) ;
.

Unmittelbar nachdem wait_until zurückkehrt, ist lock durch den aufrufenden Thread gesperrt. Wenn diese Nachbedingung nicht erfüllt werden kann [1] , ruft es std::terminate auf.

  1. 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
stoken - ein Stop-Token zur Registrierung von Unterbrechungen
abs_time - der Zeitpunkt, an dem das Warten abläuft
pred - das Prädikat zur Überprüfung, ob das Warten abgeschlossen werden kann
Typanforderungen
-
Lock muss die Anforderungen von BasicLockable erfüllen.
-
Predicate muss die Anforderungen von FunctionObject erfüllen.
-
pred ( ) muss ein gültiger Ausdruck sein, und sein Typ und Wertkategorie müssen die BooleanTestable Anforderungen erfüllen.

Rückgabewert

1) std:: cv_status :: timeout falls abs_time erreicht wurde, andernfalls std:: cv_status :: no_timeout .
2,3) Das letzte Ergebnis von pred ( ) vor der Rückkehr zum Aufrufer.

Ausnahmen

1) Zeitüberschreitungsbezogene Ausnahmen.
2,3) Zeitüberschreitungsbezogene Ausnahmen und jegliche Ausnahmen, die durch pred ausgelöst werden.

Hinweise

Die Norm 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, jedoch nicht 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 Teile von wait() / wait_for() / wait_until() (Entsperren+Warten, Aufwecken und Sperren) finden in einer einzigen Gesamtreihenfolge statt, die als Modifikationsreihenfolge einer atomaren Variable betrachtet werden kann: Die Reihenfolge ist spezifisch für diese individuelle Condition Variable. Dies macht es unmöglich, dass notify_one() beispielsweise verzögert wird und einen Thread freigibt, der gerade nach dem Aufruf von notify_one() mit dem Warten begonnen hat.

Beispiel

#include <chrono>
#include <condition_variable>
#include <iostream>
#include <thread>
std::condition_variable_any 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 Korrektes 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
(public member function)
wait_until
blockiert den aktuellen Thread, bis die Condition Variable aufgeweckt wird oder der angegebene Zeitpunkt erreicht wurde
(public member function)