std::condition_variable:: wait_until
|
template
<
class
Clock,
class
Duration
>
std::
cv_status
|
(1) | (desde C++11) |
|
template
<
class
Clock,
class
Duration,
class
Predicate
>
bool
wait_until
(
std::
unique_lock
<
std::
mutex
>
&
lock,
|
(2) | (desde C++11) |
wait_until
hace que el hilo actual se bloquee hasta que se notifique la variable de condición, se alcance el punto de tiempo dado o ocurra un despertar espurio.
pred
se puede proporcionar opcionalmente para detectar despertar espurio.
if ( wait_until ( lock, abs_time ) == std:: cv_status :: timeout )
return pred ( ) ;
return true ; .
Inmediatamente después de que
wait_until
retorne,
lock.
owns_lock
(
)
es
true
, y
lock.
mutex
(
)
está bloqueado por el hilo que realiza la llamada. Si estas postcondiciones no pueden satisfacerse
[1]
, llama a
std::terminate
.
Si se satisface cualquiera de las siguientes condiciones, el comportamiento es indefinido:
- lock. owns_lock ( ) es false .
- lock. mutex ( ) no está bloqueado por el hilo que realiza la llamada.
-
Si otros hilos también están esperando en
*
this
,
lock.
mutex
(
)
es diferente del mutex desbloqueado por las funciones de espera (
wait
,
wait_for
y
wait_until) llamadas en * this por esos hilos.
- ↑ Esto puede ocurrir si el re-bloqueo del mutex lanza una excepción.
Contenidos |
Parámetros
| lock | - | un bloqueo que debe ser adquirido por el hilo que llama |
| abs_time | - | el punto temporal donde expira la espera |
| pred | - | el predicado para verificar si la espera puede completarse |
| Requisitos de tipo | ||
-
Predicate
debe cumplir con los requisitos de
FunctionObject
.
|
||
|
-
|
||
Valor de retorno
Excepciones
Notas
El estándar recomienda que se utilice el reloj vinculado a
abs_time
para medir el tiempo; no se requiere que ese reloj sea un reloj monótono. No hay garantías respecto al comportamiento de esta función si el reloj se ajusta de manera discontinua, pero las implementaciones existentes convierten
abs_time
de
Clock
a
std::chrono::system_clock
y delegan en POSIX
pthread_cond_timedwait
para que la espera respete los ajustes del reloj del sistema, pero no los del
Clock
proporcionado por el usuario. En cualquier caso, la función también puede esperar más allá de que se haya alcanzado
abs_time
debido a demoras de planificación o contención de recursos.
Incluso si el reloj en uso es std::chrono::steady_clock u otro reloj monótono, un ajuste del reloj del sistema puede inducir un despertar espurio.
Los efectos de
notify_one()
/
notify_all()
y cada una de las tres partes atómicas de
wait()
/
wait_for()
/
wait_until()
(desbloquear+esperar, despertar y bloquear) ocurren en un único orden total que puede verse como el
orden de modificación
de una variable atómica: el orden es específico de esta variable de condición individual. Esto hace imposible que
notify_one()
pueda, por ejemplo, retrasarse y desbloquear un hilo que comenzó a esperar justo después de que se realizó la llamada a
notify_one()
.
Ejemplo
#include <chrono> #include <condition_variable> #include <iostream> #include <thread> std::condition_variable cv; std::mutex cv_m; // Este mutex se utiliza para tres propósitos: // 1) sincronizar accesos a i // 2) sincronizar accesos a std::cerr // 3) para la variable de condición 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(); }
Salida posible:
Waiting... Waiting... Waiting... Notifying... Notifying again... ...finished waiting. i == 1 ...finished waiting. i == 1 ...finished waiting. i == 1
Informes de defectos
Los siguientes informes de defectos que modifican el comportamiento se aplicaron retroactivamente a los estándares de C++ publicados anteriormente.
| DR | Se aplica a | Comportamiento publicado | Comportamiento correcto |
|---|---|---|---|
| LWG 2093 | C++11 | faltaban excepciones relacionadas con timeout en la especificación | menciona estas excepciones |
|
LWG 2114
( P2167R3 ) |
C++11 | la convertibilidad a bool era demasiado débil para reflejar las expectativas de las implementaciones | requisitos fortalecidos |
| LWG 2135 | C++11 | el comportamiento no estaba claro si lock. lock ( ) lanza una excepción | llama a std::terminate en este caso |
Véase también
|
bloquea el hilo actual hasta que la variable de condición sea activada
(función miembro pública) |
|
|
bloquea el hilo actual hasta que la variable de condición sea activada o después de la duración de tiempo de espera especificada
(función miembro pública) |