问题
I already found out with another question that Windows/MingW doesn\'t provide the nanosleep() and setitimer() alternatives to the obsolete usleep(). But my goal is to fix all warnings that cppcheck gives me, including the usleep() style warnings.
So, is there a workaround to somehow avoid usleep() on Windows without using cygwin or installing loads of new dependencies/libraries? Thanks.
回答1:
usleep()
works with microseconds. In windows for getting microsecond precesion you should use QueryPerformanceCounter() winapi function. Here you can find how get that precesion using it.
回答2:
I used this code from (originally from 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);
}
Note that SetWaitableTimer() uses "100 nanosecond intervals ... Positive values indicate absolute time. ... Negative values indicate relative time." and that "The actual timer accuracy depends on the capability of your hardware."
If you have a C++11 compiler then you can use this portable version:
#include <chrono>
#include <thread>
...
std::this_thread::sleep_for(std::chrono::microseconds(usec));
Kudos to Howard Hinnant who designed the amazing <chrono>
library (and whose answer below deserves more love.)
If you don't have C++11, but you have boost, then you can do this instead:
#include <boost/thread/thread.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
...
boost::this_thread::sleep(boost::posix_time::microseconds(usec));
回答3:
New answer for an old question:
Rationale for the new answer: Tools / OSs have been updated such that there is a better choice now than there was when the question was originally asked.
The C++11 <chrono>
and <thread>
std headers have been in the VS toolset for several years now. Using these headers this is best coded in C++11 as:
std::this_thread::sleep_for(std::chrono::microseconds(123));
I'm using microseconds only as an example duration. You can use whatever duration happens to be convenient:
std::this_thread::sleep_for(std::chrono::minutes(2));
With C++14 and some using directives, this can be written a little bit more compactly:
using namespace std::literals;
std::this_thread::sleep_for(2min);
or:
std::this_thread::sleep_for(123us);
This definitely works on VS-2013 (modulo the chrono-literals). I'm unsure about earlier versions of VS.
回答4:
The millisecond regime of the Sleep()
function is well described and well understood. It does not do anything unpredictable. Sometimes the function is blamed to perform unpredictable, i.e. returning before the delay has expired. I need to say that this is wrong. Careful investigation will confirm that its behaviour is absolutely predictable. The only problem is
that there is plenty to read about it and most of it is kiddish. It is also often said that
windows it not a real-time OS. But such comments don't contribute anything, moreover such
comments are used to hide the lack of knowledge. It makes me sort of angry, that not even
microsoft notices this and provides better documentation.
However, without exaggerating this little answer: The sleep() function is precise, when used in a proper way and when knowing its characteristics. Particular attention has to be given to sleep(0). This is a very powerfull tool, particulary when used together with process priority class, thread priority, multimedia timer settings, and processor affinity mask.
So generally a true sleep can be performed easely and safe down to the systems interrupt period. When it comes to sleeps shorter than the interrupt period spinning is required.
A higher resolution time source has to be used in oder to spin for shorter periods in time.
The most common source for this is the performance counter. QueryPerformanceCounter(*arg)
delivers an incrementing *arg. QueryPerformanceFrequency(*arg)
delivers the frequency at which the performance counter increments. This is typically in the MHz regime and varies, depending on the underlying hardware. A frequency in the MHz range provides microsecond resolution. This way something of high resolution can be used to wait for a desired time span to expire. However, the accuracy of this has to be looked at carefully: The OS returns the performance counter frequency as a constant. This is wrong! Since the frequency is generated be a physical device, there is always an offset and it also not a
constant. It has thermal drift. More modern systems do have less drift. But if the thermal drift is just 1ppm, the error will be 1us/s. The offset can easely be several 100. An offset of 100 in 1MHz corresponds to 100us/s.
If a thread shall wait for any time at high resolution, it shall establish a service thread. Both thread shall share a named event. The service thread shall sleep until 1 interrupt period ahead of the desired sleep delay and then spin on the performance counter for the remaining microsecond. When the service thread reaches the final time, it set the named event and ends. The calling thread will wake up, because it was waiting for the named event by means of a wait function.
Summary:
- Sleep is well understood but poorly documented.
- A service thread can mimic sleeps at high resolution.
- Such a service thread coulb be esablished as a system wide service.
- Accuracy of the performance counter is to be looked at carefully. A calibration is required.
More detailed information can be found at the Windows Timestamp Project
回答5:
It depends what granularity you need. If you are talking milliseconds, then the Win32 Sleep function will do the job - see http://msdn.microsoft.com/en-us/library/ms686298%28v=vs.85%29.aspx. If you are talking microseconds, then there is no easy way to do it, and you would be lucky to get that sort of timer resolution on Windows (which is not an RTOS), or on Linux, come to that.
回答6:
I found this blog post about it. It uses QueryPerformanceCounter
. The function posted:
#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);
}
I hope this helps a bit.
来源:https://stackoverflow.com/questions/5801813/c-usleep-is-obsolete-workarounds-for-windows-mingw