Saltar al contenido

c ++, usleep () es obsoleto, ¿soluciones alternativas para Windows / MingW?

Solución:

Usé este código de (originalmente de aquí):

#include <windows.h>

void usleep(__int64 usec) 
{ 
    HANDLE timer; 
    LARGE_INTEGER ft; 

    ft.QuadPart = -(10*usec); // Convert to 100 nanosecond interval, negative value indicates relative time

    timer = CreateWaitableTimer(NULL, TRUE, NULL); 
    SetWaitableTimer(timer, &ft, 0, NULL, NULL, 0); 
    WaitForSingleObject(timer, INFINITE); 
    CloseHandle(timer); 
}

Tenga en cuenta que SetWaitableTimer() usos “Intervalos de 100 nanosegundos … Los valores positivos indican tiempo absoluto. … Los valores negativos indican tiempo relativo.” y eso “La precisión real del temporizador depende de la capacidad de su hardware.

Si tiene un compilador de C ++ 11, puede usar esta versión portátil:

#include <chrono>
#include <thread>
...
std::this_thread::sleep_for(std::chrono::microseconds(usec));

Felicitaciones a Howard Hinnant, quien diseñó el increíble <chrono> biblioteca (y cuya respuesta a continuación merece más amor).

Si no tiene C ++ 11, pero tiene boost, puede hacer esto en su lugar:

#include <boost/thread/thread.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
...
boost::this_thread::sleep(boost::posix_time::microseconds(usec));

Nueva respuesta para una vieja pregunta:

Justificación de la nueva respuesta: Las herramientas / sistemas operativos se han actualizado de tal manera que ahora hay una mejor opción que cuando se hizo la pregunta originalmente.

El C ++ 11 <chrono> y <thread> Los encabezados std han estado en el conjunto de herramientas de VS durante varios años. Usando estos encabezados, esto se codifica mejor en C ++ 11 como:

std::this_thread::sleep_for(std::chrono::microseconds(123));

Estoy usando microsegundos solo como duración de ejemplo. Puede usar la duración que le resulte conveniente:

std::this_thread::sleep_for(std::chrono::minutes(2));

Con C ++ 14 y algunas directivas de uso, esto se puede escribir de forma un poco más compacta:

using namespace std::literals;
std::this_thread::sleep_for(2min);

o:

std::this_thread::sleep_for(123us);

Esto definitivamente funciona en VS-2013 (módulo los crono-literales). No estoy seguro de las versiones anteriores de VS.

El régimen de milisegundos del Sleep() la función está bien descrita y bien entendida. No hace nada impredecible. A veces se culpa a la función de realizar de forma impredecible, es decir, que regresa antes de que expire la demora. Necesito decir que esto está mal. Una investigación cuidadosa confirmará que su comportamiento es absolutamente predecible. El único problema es que hay mucho que leer al respecto y la mayor parte es infantil. También se suele decir que Windows no es un sistema operativo en tiempo real. Pero tales comentarios no aportan nada, además tales comentarios se utilizan para ocultar la falta de conocimiento. Me enoja un poco que ni siquiera microsoft se dé cuenta de esto y proporcione una mejor documentación.

Sin embargo, sin exagerar esta pequeña respuesta: La función sleep () es precisa, cuando se usa de manera adecuada y al conocer sus características. Se debe prestar especial atención al sueño (0). Esta es una herramienta muy poderosa, particularmente cuando se usa junto con la clase de prioridad de proceso, la prioridad de subproceso, la configuración del temporizador multimedia y la máscara de afinidad del procesador.

Por lo tanto, en general, un verdadero sueño se puede realizar de manera fácil y segura hasta el período de interrupción del sistema. Cuando se trata de dormir más cortos que el período de interrupción, se requiere centrifugado. Se debe utilizar una fuente de tiempo de mayor resolución para poder girar durante períodos de tiempo más cortos. La fuente más común de esto es el contador de rendimiento. QueryPerformanceCounter(*arg) entrega un * arg incremental. QueryPerformanceFrequency(*arg) entrega la frecuencia a la que aumenta el contador de rendimiento. Por lo general, se encuentra en el régimen de MHz y varía según el hardware subyacente. Una frecuencia en el rango de MHz proporciona una resolución de microsegundos. De esta manera, se puede usar algo de alta resolución para esperar a que expire el período de tiempo deseado. Sin embargo, la precisión de esto debe analizarse detenidamente: el sistema operativo devuelve la frecuencia del contador de rendimiento como una constante. ¡Esto está mal! Dado que la frecuencia se genera en un dispositivo físico, siempre hay un desplazamiento y tampoco una constante. Tiene deriva térmica. Los sistemas más modernos tienen menos deriva. Pero si la deriva térmica es de solo 1 ppm, el error será de 1 us / s. El desplazamiento puede ser fácilmente varios 100. Un desplazamiento de 100 en 1MHz corresponde a 100us / s.

Si un hilo debe esperar en cualquier momento en alta resolución, establecerá un hilo de servicio. Ambos subprocesos compartirán un evento con nombre. El subproceso de servicio dormirá hasta 1 período de interrupción antes de la demora de suspensión deseada y luego girará en el contador de rendimiento durante el microsegundo restante. Cuando el hilo de servicio llega a la hora final, establece el evento con nombre y finaliza. El hilo de llamada se despertará, porque estaba esperando el evento nombrado por medio de una función de espera.

Resumen:

  • El sueño se comprende bien pero está mal documentado.
  • Un hilo de servicio puede imitar los durmientes en alta resolución.
  • Dicho hilo de servicio podría establecerse como un servicio de todo el sistema.
  • La precisión del contador de rendimiento debe examinarse detenidamente. Se requiere una calibración.

Puede encontrar información más detallada en el Proyecto de marca de tiempo de Windows

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *