c++, usleep() is obsolete, workarounds for Windows/MingW?
Asked Answered
P

7

38

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.

Plumbago answered 27/4, 2011 at 9:15 Comment(5)
What are you using usleep for?Elwin
related question: #85622 (I thought of proposing to use select as alternative)Coarctate
Using select is a great idea. It is not terribly efficient, but then again when one is waiting, who cares. On the other hand, it is as portable as you can get. There exists no serious platform that doesn't have select.Striation
just blindly trying to resolve all warnings issued by cppcheck, without reflecting on their rationale, and what that means for your project, does not seem to be the best ideaDormeuse
There's nothing obsolete about usleep.Benavides
U
-2

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.

Underexpose answered 27/4, 2011 at 9:26 Comment(2)
While QueryPerformanceCounter can give high-resolution clock values, it is not a real-time sleeping API -- it can only allow you to busy-wait.Rejoice
Nothing in Windows is "real time." For values in microsecond or nanosecond range, sleeping isn't a concept. The Windows scheduler uses quanta on the order of 10s of milliseconds. Unless you're doing it constantly, a busy wait on the order of microseconds isn't horrible.Coffeng
A
65

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));
Androgynous answered 24/6, 2013 at 19:30 Comment(6)
And if you have C++14 you can use the ms user defined literal, as in std::this_thread::sleep_for(100ms);. This only works on constant values (obviously), and requires a using directive. See this answer for details.Indihar
GCC implementation of std::this_thread::sleep_for will use ::nanosleep when supported, but ::Sleep on Windows with millisecond resolution. Don't know about VS one.Frolicsome
Wouldn't a call to WaitForSingleObject cause the process to yield it's time slice and thereby cause a context switch? If so, the function is pretty much guaranteed to never wait accurately, as per design.Centrum
MSDN link in above answer now redirects to learn.microsoft.com/en-gb/windows/win32/api/synchapi/… - but the edit queue is full and I can't update it just now.Circumstance
The c-plusplus DOT de link also redirects, to c-plusplus.net/forum/topic/109539/usleep-unter-windowsCircumstance
I can confirm on Windows 10 / Intel CPU that this usleep implementation has 16 ms accuracy / granularity, exactly the same as regular Sleep()Untruthful
B
25

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.

Battle answered 31/8, 2015 at 20:9 Comment(4)
Just the other day, I ran into a Windows-only deadlock in a trivial test program that used sleep_for to wait for a few microseconds. MS's implementation seems to boil down to Sleep (or the equivalent), which takes milliseconds. Calling sleep_for for less than a millisecond translates to Sleep(0). The Sleep() documentation explains that Sleep(0) can cause a deadlock when called from a threadpool thread under certain circumstances, and those circumstances were common in our test suite. Calling sleep_for with milliseconds resolved the problem.Coffeng
That sounds like it is worthy of a bug report. The implementation should round finer precisions up to the next sleep-able precision, not down.Battle
@AdrianMcCarthy It's not the Sleep itself that's causing a deadlock, if your threadpool had a deadlock it's probably because the thread was stuck in a while-true loop (Which never yielded to another thread, since it was in a busy loop)Drub
@NicholasPipitone: You are correct that the implementation of Sleep is not causing the deadlock. If thread A is waiting for thread B to complete some work, and thread A uses Sleep(0) to yield its timeslice, there's no guarantee that thread B will be scheduled. Usually, B will be scheduled (eventually), but there are circumstances where it never will be. If A used Sleep(1) instead of Sleep(0), then B would eventually be scheduled (barring other bugs, like a priority inversion) and thus B can complete its work, allowing A to proceed.Coffeng
M
14

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

Manatee answered 13/7, 2012 at 12:33 Comment(6)
Not quite! The resolution is not necessarily the inverse of the reported frequency — On one of my boxes, QPF() returns the nominal CPU clock frequency but QPC() always returns a multiple of 10. I'm guessing this is due to the implementation of an "invariant TSC" a.k.a. constant_tsc.Beefcake
@tc.: Did I suggest to not trust the result of QPF? Yes I did, because its result never shows the truth, it never shows the physical frequency. It shall be considered as an estimated constant. Reporting the CPU clock frequency in 1Hz units is somewhat stupid. Even units of 10 are ridiculous because the real frequency deviates by several ppm. 1ppm equals 2000Hz on a 2GHz hardware. So a more realistic granularity for the output of QPF should/could be 1ppm of the frequency. BTW: This would give people also the hint that the output of QPF is only an estimate.Manatee
I was specifically responding to "A frequency in the MHz range provides microsecond resolution" and I think you misinterpreted me: My results suggest that QPC() counts up steps of 10 on one of my boxes, giving a resolution of about 1/(240 MHz); not 1/(2.4 GHz). Clock drift/skew is another can of worms entirely...Beefcake
@tc.: Well, 1/240MHz is ~ 4ns. That's far better than microsecond resolution as well. And: Of course the resolution is also determined by the quantisation/granularity (presumed in all of the above).Manatee
@tc: ... was just brought to my attention: constant TSC would return QPF() with CPU freq./1024. The CPU freq. does not exist by hardware, it is gernerated by a frequency multiplier (1024).Manatee
Arno, your Timestamp Project site provides incredible in-depth research to all things time on Windows, up to Windows 8.1. Chapeau!Aboulia
A
6

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.

Annettannetta answered 27/4, 2011 at 9:26 Comment(0)
H
3

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.

Homochromous answered 27/4, 2011 at 9:20 Comment(4)
This is a busy wait. It will waste CPU cycles.Affusion
@tibor Yes it will. As far as I know the windows process scheduler does not provide any sleep procedure with microsecond precision. You can create a hybrid sleep function though, use the default Sleep function for the milliseconds and use busy waiting for the last small wait time. This can reduce the performance hit to less than 5 ms of busy waiting without sacrificing precision.Homochromous
The current code is ignoring the value of freq. Instead, if waitTime is given in microseconds, the final test should be time2-time1 < waitTime*freq/1000000 .Paquito
This will work, but is inefficient. At least throw _mm_pause() inside the loop.Untruthful
A
2

I'm quite late to the party but I want just to add something to this question. If you want to achieve portability using microseconds resolution than use select() system call using empty file descriptor set. It will work both on linux and on windows, i.e. it can be called using an uniform interface (the behavior can be still different especially on Windows where you can ask for 1 microsecond but you get 1ms sleep). If you want to use a third-party library use Boost, but a recent version. The time related std api are just a mess and I provide a summary here:

  1. Windows: sleep_for, sleep_until, condition_variable, future and so on wait_for/wait_until methods are totally unreliable because they are based on system_clock, so if the time changes your application could hang. They fixed this problem internally but since it's an ABI break, they didn't release it yet, not available even on latest VS 2019.
  2. Linux: sleep_for, sleep_until are ok, but condition_variable/future wait_for/wait_until are unreliable because they are based too on system clock. It's fixed with Gcc 10 and GlibC 2.6 bug link.
  3. Boost: Same as above but they fixed time problems with version 1.67.

So if you want portable code make your own solution or just use Boost 1.67+, don't trust standard implementation c++11 chrono because the implementation performed is really bad.

Aerodontia answered 29/12, 2019 at 12:9 Comment(0)
U
-2

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.

Underexpose answered 27/4, 2011 at 9:26 Comment(2)
While QueryPerformanceCounter can give high-resolution clock values, it is not a real-time sleeping API -- it can only allow you to busy-wait.Rejoice
Nothing in Windows is "real time." For values in microsecond or nanosecond range, sleeping isn't a concept. The Windows scheduler uses quanta on the order of 10s of milliseconds. Unless you're doing it constantly, a busy wait on the order of microseconds isn't horrible.Coffeng

© 2022 - 2024 — McMap. All rights reserved.