variable thread condition_variable c++ multithreading c++11 condition-variable

c++ - thread - ¿Cuál es la diferencia entre std:: condition_variable:: wait_for y std:: condition_variable:: wait_until?



c++ std:: condition_variable (4)

Aquí hay una diferencia importante en su uso, como se explica en el book Anthony Williams:

Considere este ejemplo donde se espera una variable de condición con un tiempo de espera:

std::condition_variable cv; bool done; std::mutex m; bool wait_loop() { auto const timeout= std::chrono::steady_clock::now()+ std::chrono::milliseconds(500); std::unique_lock<std::mutex> lk(m); while(!done) { if(cv.wait_until(lk,timeout)==std::cv_status::timeout) break; } return done; }

Esta es la forma recomendada de esperar las variables de condición con un límite de tiempo, si no está pasando un predicado a la espera. De esta manera, la longitud total del bucle está acotada . Como se vio en la sección 4.1.1, debe realizar un bucle cuando use variables de condición si no pasa el predicado, para manejar activaciones falsas. Si usa wait_for() en un bucle, puede terminar esperando casi todo el tiempo antes de una activación falsa, y la próxima vez que comience el tiempo de espera comienza nuevamente. Esto puede repetirse cualquier número de veces, haciendo que el tiempo total de espera sea ilimitado .

En mi opinión, este es un escenario en el que wait_for no puede reemplazar a wait_until tan fácilmente, debido a su naturaleza de restablecimiento.

La referencia que estoy usando explica los dos de la siguiente manera:

  • wait_for "bloquea el subproceso actual hasta que la variable de condición se despierte o después del tiempo de espera especificado"

  • wait_until "bloquea el subproceso actual hasta que la variable de condición se despierte o hasta que se alcance el punto de tiempo especificado"

¿Cuál es la diferencia? ¿ wait_until para que el hilo pueda continuar exactamente (más o menos) cuando esté señalado, mientras que wait_for simplemente wait_for a agregar el hilo a la programación en ese momento?


La diferencia está en cómo se representa la duración de la espera: wait_for toma un tiempo relativo ("esperar hasta 10 segundos"), mientras que wait_until toma un tiempo absoluto ("esperar hasta las 12:00 el 30 de octubre de 2012").

Compara las declaraciones de los parámetros de tiempo:

// wait_for: const std::chrono::duration<Rep, Period>& rel_time // wait_until: const std::chrono::time_point<Clock, Duration>& abs_time


Tu pregunta y otras respuestas han repetido la diferencia; ese wait_for espera por un período de tiempo wait_until y wait_until espera hasta un punto específico en el tiempo, pero las implicaciones no están explicadas.

Un time_point tiene un reloj asociado, y ese reloj es lo que se usa para determinar si ha llegado el momento adecuado. Eso significa que los ajustes de reloj son tomados en cuenta por la función wait_until . wait_until(..., system_clock::now() + std::chrono::seconds(10)) podría terminar esperando una hora y 10 segundos si el reloj vuelve a ajustarse una hora antes de que finalice la espera.

Una duración no tiene un reloj asociado y, por wait_for tanto, wait_for elige su propio reloj. El estándar especifica que usa std :: steady_clock, que no se puede ajustar y avanza a una velocidad constante en relación con el tiempo real. Esto significa que wait_for esperará el tiempo especificado independientemente de los ajustes realizados en los relojes. wait_for(..., std::chrono::seconds(10)) esperará 10 segundos (+ algún tiempo para que la implementación funcione y para los problemas de programación).

No hay diferencia con respecto a girar o dormir el hilo; como wait_for se especifica para comportarse como si se llamara wait_until con steady_clock::now() + duration .

Aquí está la parte de la norma donde se explica esto:

[thread.req.timing] 30.2.4 / 2-4

2 Las implementaciones necesariamente tienen algún retraso en volver de un tiempo de espera. Cualquier sobrecarga en la respuesta de interrupción, el retorno de la función y la programación induce un retraso en la "calidad de la implementación", expresado como duración D i . Idealmente, este retraso sería cero. Además, cualquier disputa por los recursos del procesador y la memoria induce un retraso en la "calidad de gestión", expresado como duración D m . Las duraciones de retardo pueden variar de un tiempo de espera a otro, pero en todos los casos, más corto es mejor.

3 Las funciones miembro cuyos nombres terminan en _for tomar un argumento que especifica una duración. Estas funciones producen tiempos de espera relativos. Las implementaciones deben usar un reloj estable para medir el tiempo de estas funciones. Dado un argumento de duración D t , la duración en tiempo real del tiempo de espera es D t + D i + D m .

4 Las funciones miembro cuyos nombres terminan en _until tomen un argumento que especifica un punto de tiempo. Estas funciones producen tiempos de espera absolutos. Las implementaciones deben usar el reloj especificado en el punto de tiempo para medir el tiempo para estas funciones. Dado un argumento de punto de tiempo de reloj C t , el punto de tiempo de reloj del retorno de tiempo de espera debe ser C t + D i + D m cuando el reloj no se ajusta durante el tiempo de espera. Si el reloj se ajusta a la hora C a durante el tiempo de espera, el comportamiento debe ser el siguiente:
- Si C a > C t , la función de espera debería activarse lo antes posible, es decir, C a + D i + D m , ya que el tiempo de espera ya está satisfecho. [ Nota: Esta especificación puede dar como resultado que la duración total de la espera disminuya cuando se mide contra un reloj estable. "Nota final "

- si C a <= C t , la función de espera no debe expirar hasta que Clock::now() devuelva una hora C n > = C t , es decir, despertarse en C t + D i + D m . [ Nota: cuando el reloj se ajusta al revés, esta especificación puede resultar en que la duración total de la espera aumente cuando se mide contra un reloj estable. Cuando el reloj se ajusta hacia adelante, esta especificación puede dar como resultado que la duración total de la espera disminuya cuando se mide contra un reloj estable. "Nota final "

Una implementación regresará de dicho tiempo de espera en cualquier punto desde el tiempo especificado anteriormente hasta el tiempo que regresaría de un tiempo de espera relativo de reloj constante en la diferencia entre C t y el punto de tiempo de la llamada a la función hasta el _until . [ Nota: Las implementaciones deben disminuir la duración de la espera cuando el reloj se ajusta hacia adelante. "Nota final "


  • wait_for esperará por un cierto tiempo. Por ejemplo, esperará dos segundos.
  • wait_until esperará hasta que se alcance algún tiempo. Por ejemplo, esperará hasta el 23 de julio de 2013 a las 11:22:34 pm en el reloj.