std::condition_variable_any::wait_for
template< class Lock, class Rep, class Period > std::cv_status wait_for( Lock& lock, const std::chrono::duration<Rep, Period>& rel_time); |
(1) | (desde C++11) |
template< class Lock, class Rep, class Period, class Predicate > bool wait_for( Lock& lock, const std::chrono::duration<Rep, Period>& rel_time, Predicate pred); |
(2) | (desde C++11) |
template< class Lock, class Rep, class Period, class Predicate > bool wait_for( Lock& lock, std::stop_token stoken, const std::chrono::duration<Rep, Period>& rel_time, Predicate pred); |
(3) | (desde C++20) |
lock, bloquea el hilo en ejecución actual y lo agrega a la lista de hilos en espera de *this. El hilo se desbloqueará cuando se ejecute notify_all() o notify_one(), o cuando el tiempo de espera relativo rel_time expire. También se puede desbloquear de forma espuria. Cuando se desbloquea, independientemente del motivo, se vuelve a tomar posesión de lock y wait_for() sale.return wait_until(lock, std::chrono::steady_clock::now() + rel_time, std::move(pred));. Esta sobrecarga se puede utilizar para ignorar los despertares espurios.return wait_until(lock, std::move(stoken), std::chrono::steady_clock::now() + rel_time, std::move(pred));El estándar recomienda que se utilice un reloj fijo para medir la duración. Esta función puede bloquearse por más de timeout_duration debido a demoras en la programación o en la contención de recursos.
Si estas funciones no cumplen con la poscondición (lock se bloquea por el hilo llamante), se llama a std::terminate. Por ejemplo, esto podría suceder si al volver a bloquear el mutex se lanza una excepción.
Parámetros
| lock | - | Un objeto de tipo Lock que cumple con los requerimientos de BasicLockable, que debe estar bloqueado por el hilo actual.
|
| stoken | - | Un símbolo de detención std::stop_token para el cual registrar la interrupción.
|
| rel_time | - | Un objeto de tipo std::chrono::duration que representa el tiempo máximo de espera. Ten en cuenta que rel_time debe ser lo suficientemente pequeño como para no desbordarse cuando se agrega a std::chrono::steady_clock::now().
|
| pred | - | Predicado que devuelve false si la espera debería continuar.. La signatura de la función predicado deberá ser equivalente a lo siguiente:
|
Valor de retorno
rel_time expiró, std::cv_status::no_timeout de lo contrario.false si el predicado pred todavía se evalúa a false después de que el tiempo de espera rel_time expiró, true de lo contrario.pred(), independientemente de si el tiempo de espera se cumplió o se solicitó una detención.Excepciones
pred.Notas
Incluso si se notifica bajo bloqueo, la sobrecarga (1) no garantiza el estado del predicado asociado cuando regresa debido al tiempo de espera.
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) tienen lugar en un solo orden total que se puede ver como el orden de modificación de una variable atómica: el orden es específico para esta variable de condición individual. Esto hace imposible que notify_one() por ejemplo, se retrase y desbloquee un hilo que comenzó a esperar justo después de que se hizo la llamada a notify_one().
Ejemplo
#include <iostream>
#include <atomic>
#include <condition_variable>
#include <thread>
#include <chrono>
using namespace std::chrono_literals;
std::condition_variable_any cv;
std::mutex cv_m;
int i;
void espera(int idx)
{
std::unique_lock<std::mutex> lk(cv_m);
if(cv.wait_for(lk, idx*100ms, []{return i == 1;}))
std::cerr << "Hilo " << idx << " ha terminado la espera. i == " << i << '\n';
else
std::cerr << "Hilo " << idx << " agotado. i == " << i << '\n';
}
void indica()
{
std::this_thread::sleep_for(120ms);
std::cerr << "Notificando...\n";
cv.notify_all();
std::this_thread::sleep_for(100ms);
{
std::lock_guard<std::mutex> lk(cv_m);
i = 1;
}
std::cerr << "Notificando de nuevo...\n";
cv.notify_all();
}
int main()
{
std::thread t1(espera, 1), t2(espera, 2), t3(espera, 3), t4(indica);
t1.join();
t2.join();
t3.join();
t4.join();
}
Salida:
Hilo 1 agotado. i == 0
Notificando...
Hilo 2 agotado. i == 0
Notificando de nuevo...
Hilo 3 ha terminado la espera. i == 1
Informes de defectos
Los siguientes informes de defectos de cambio de comportamiento se aplicaron de manera retroactiva a los estándares de C++ publicados anteriormente.
| ID | Aplicado a | Comportamiento según lo publicado | Comportamiento correcto |
|---|---|---|---|
| LWG 2093 | C++11 | Faltaban excepciones relacionadas con el tiempo de espera en la especificación. | Se mencionan. |
| LWG 2135 | C++11 | wait_for lanzaba una excepción cuando fallaba el desbloqueo y rebloqueo.
|
Llama a std::terminate. |
Véase también
| Bloquea el hilo actual hasta que la variable de condición se despierte. (función miembro pública) | |
| Bloquea el hilo actual hasta que la variable de condición se despierte o se haya alcanzado el punto de tiempo especificado. (función miembro pública) |