Pregunta

Ya descubrí con otra pregunta que Windows/Mingw no proporciona alternativas nanosleep () y setitimer () al obsoleto usleep (). Pero mi objetivo es arreglar todas las advertencias que CPPCheck me da, incluidas las advertencias de estilo usleep ().

Entonces, ¿hay una solución para evitar de alguna manera useep () en Windows sin que ¿Usar cygwin o instalar cargas de nuevas dependencias/bibliotecas? Gracias.

¿Fue útil?

Solución

usleep() Funciona con microsegundos. En Windows para obtener precesiones de microsegundos, debe usar QueryperformancEdter () Función Winapi. Aquí Puede encontrar cómo obtener esa precesión lo usa.

Otros consejos

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 "100 intervalos de nanosegundos ... los valores positivos indican tiempo absoluto. ... Los valores negativos indican tiempo relativo." y eso "La precisión del temporizador real depende de la capacidad de su hardware."

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

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

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

Si no tienes C ++ 11, pero tienes impulso, entonces puedes hacer este en cambio:

#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 / OSS se han actualizado de manera que hay una mejor opción ahora que cuando la pregunta se hizo originalmente.

El C ++ 11 <chrono> y <thread> Los encabezados STD han estado en el conjunto de herramientas 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 una duración de ejemplo. Puede usar cualquier duración que sea conveniente:

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

Con C ++ 14 y algunos usando directivas, esto se puede escribir un poco más compacto:

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 de crono-literales). No estoy seguro de 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 para que funcione impredecible, es decir, regresar antes de que el retraso haya expirado. Necesito decir que esto está mal. La investigación cuidadosa confirmará que su comportamiento es absolutamente predecible. El único problema es que hay mucho para leer al respecto y la mayor parte es infantil. También a menudo se dice que Windows no es un sistema operativo en tiempo real. Pero tales comentarios no contribuyen nada, además, tales comentarios se utilizan para ocultar la falta de conocimiento. Me enoja, que ni siquiera Microsoft nota esto y proporciona 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 del proceso, la prioridad de subprocesos, la configuración del temporizador multimedia y la máscara de afinidad del procesador.

Por lo tanto, en general, un sueño verdadero se puede realizar fácilmente y seguro hasta el período de interrupción de los sistemas. Cuando se trata de dormir más corto que el hilado del período de interrupción. Una fuente de tiempo de resolución más alta debe usarse en Oder para girar durante períodos más cortos en el tiempo. La fuente más común para esto es el contador de rendimiento. QueryPerformanceCounter(*arg) entrega un incremento *Arg. QueryPerformanceFrequency(*arg) entrega la frecuencia a la que el rendimiento contiene incrementos. Esto suele estar en el régimen de MHZ y varía, dependiendo del hardware subyacente. Una frecuencia en el rango MHZ proporciona resolución de microsegundos. De esta manera, se puede usar algo de alta resolución para esperar un lapso de tiempo deseado para expirar. Sin embargo, la precisión de esto debe considerarse cuidadosamente: el sistema operativo devuelve la frecuencia del contador de rendimiento como una constante. ¡Esto está mal! Dado que la frecuencia se genera es un dispositivo físico, siempre hay un desplazamiento y tampoco es 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á 1US/s. El desplazamiento puede ser de forma fácil de 100. Un desplazamiento de 100 en 1MHz corresponde a 100US/s.

Si un hilo espera cualquier tiempo a alta resolución, establecerá un hilo de servicio. Ambos hilo compartirán un evento nombrado. El hilo de servicio dormirá hasta 1 período de interrupción antes del retraso de sueño deseado y luego girar en el contador de rendimiento para el microsegundo restante. Cuando el hilo de servicio llega a la última vez, establece el evento nombrado y termina. El hilo de llamadas se despertará, porque estaba esperando el evento nombrado por medio de una función de espera.

Resumen:

  • El sueño se entiende bien pero está mal documentado.
  • Un hilo de servicio puede imitar los durmientes a alta resolución.
  • Tal servicio de servicio se establece como un servicio amplio del sistema.
  • La precisión del contador de rendimiento debe ser considerado cuidadosamente. Se requiere una calibración.

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

Depende de la granularidad que necesite. Si está hablando de milisegundos, entonces la función de sueño Win32 hará el trabajo - ver http://msdn.microsoft.com/en-us/library/ms686298%28v=vs.85%29.aspx. Si está hablando de microsegundos, entonces no hay una manera fácil de hacerlo, y tendrá la suerte de obtener ese tipo de resolución de temporizador en Windows (que no es un RTOS), o en Linux, llegue a eso.

encontré Esta publicación de blog al respecto. Usa QueryPerformanceCounter. La función publicada:

#include <windows.h>

void uSleep(int waitTime) {
    __int64 time1 = 0, time2 = 0, freq = 0;

    QueryPerformanceCounter((LARGE_INTEGER *) &time1);
    QueryPerformanceFrequency((LARGE_INTEGER *)&freq);

    do {
        QueryPerformanceCounter((LARGE_INTEGER *) &time2);
    } while((time2-time1) < waitTime);
}

Espero que esto ayude un poco.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top