c++ windows cppcheck usleep

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



cppcheck (6)

Ya descubrí con otra pregunta que Windows / MingW no proporciona las alternativas nanosleep () y setitimer () a la obsoleta usleep (). Pero mi objetivo es arreglar todas las advertencias que me da cppcheck, incluidas las advertencias de estilo usleep ().

Entonces, ¿hay una solución para evitar de alguna manera usleep () en Windows sin usar cygwin o instalar un montón de nuevas dependencias / bibliotecas? Gracias.


Depende de la granularidad que necesites. Si está hablando milisegundos, entonces la función Win32 Sleep hará el trabajo, consulte 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ía la suerte de obtener ese tipo de resolución de temporizador en Windows (que no es un RTOS), o en Linux.


El régimen de milisegundos de la función Sleep() está bien descrito y bien entendido. No hace nada impredecible. A veces se culpa a la función por su desempeño impredecible, es decir, regresar antes de que el retraso haya expirado. 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ía es infantil. También se suele decir que Windows no es un sistema operativo en tiempo real. Pero tales comentarios no contribuyen en nada, además, tales comentarios se usan para ocultar la falta de conocimiento. Me enoja, que ni siquiera Microsoft lo nota y proporciona una mejor documentación.

Sin embargo, sin exagerar esta pequeña respuesta: la función sleep () es precisa, cuando se utiliza de manera adecuada y cuando conoce sus características. Hay que 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, prioridad de hilo, configuración del temporizador multimedia y máscara de afinidad del procesador.

Por lo general, un verdadero sueño puede realizarse de manera fácil y segura hasta el período de interrupción de los sistemas. Cuando se trata de dormir más corto que el período de interrupción, es necesario girar. Se debe utilizar una fuente de tiempo de mayor resolución en orden 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 * arg creciente. QueryPerformanceFrequency(*arg) entrega la frecuencia a la que se incrementa el contador de rendimiento. Esto suele estar en el régimen de MHz y varía, dependiendo del hardware subyacente. Una frecuencia en el rango de MHz proporciona una resolución de microsegundos. De esta manera, se puede utilizar algo de alta resolución para esperar a que caduque el período de tiempo deseado. 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 en un dispositivo físico, siempre hay un desplazamiento y no 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 fácilmente de varios 100. Un desplazamiento de 100 en 1MHz corresponde a 100us / s.

Si un subproceso esperará en cualquier momento a alta resolución, establecerá un subproceso de servicio. Ambos hilos compartirán un evento nombrado. El subproceso de servicio estará en espera hasta 1 período de interrupción antes del retraso de reposo deseado 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 nombrado y finaliza. El hilo de llamada se activará porque estaba esperando el evento nombrado por medio de una función de espera.

Resumen:

  • El sueño es bien entendido pero mal documentado.
  • Un hilo de servicio puede imitar el sueño en alta resolución.
  • Este hilo de servicio puede ser establecido como un servicio de todo el sistema.
  • La precisión del contador de rendimiento debe examinarse cuidadosamente. Se requiere una calibración.

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


He encontrado esta entrada de blog al respecto . Utiliza 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.


Nueva respuesta para una vieja pregunta:

Razón de la nueva respuesta: las herramientas / sistemas operativos se han actualizado de modo que ahora hay una mejor opción que cuando se formuló la pregunta originalmente.

Los encabezados estándar C ++ 11 <chrono> y <thread> 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 un ejemplo de duración. Puede usar cualquier duración que le resulte 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 (modulo los crono-literales). No estoy seguro acerca de las versiones anteriores de VS.


Utilicé este código desde (originalmente desde here ):

#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() utiliza " intervalos de 100 nanosegundos ... Los valores positivos indican el tiempo absoluto ... Los valores negativos indican el tiempo relativo " y que " la precisión real del temporizador depende de la capacidad de su hardware " .

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

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

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

Si no tiene C ++ 11, pero tiene impulso, puede hacer this en this lugar:

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


usleep() trabaja con microsegundos. En las ventanas para obtener la versión de microsegundos, debe usar la función winapi QueryPerformanceCounter() . Here puedes encontrar cómo conseguir esa precesión usándolo.