Sleeping for milliseconds on Windows, Linux, Solaris, HP-UX, IBM AIX, Vxworks, Wind River Linux?
Solution 1
Propably a wrapper using platform specific #define
s will do:
#if defined(WIN32)
#include <windows.h>
#elif defined(__UNIX__)
#include <unistd.h>
#else
#endif
...
int millisleep(unsigned ms)
{
#if defined(WIN32)
SetLastError(0);
Sleep(ms);
return GetLastError() ?-1 :0;
#elif defined(LINUX)
return usleep(1000 * ms);
#else
#error ("no milli sleep available for platform")
return -1;
#endif
}
Update
Referring to Jonathan's comment below, please find a more modern, more portable (and as well corrected :}) version here:
#if defined(WIN32)
#include <windows.h>
#elif defined(__unix__)
#include <time.h>
#include <unistd.h>
#else
#endif
...
int millisleep(unsigned ms)
{
#if defined(WIN32)
SetLastError(0);
Sleep(ms);
return GetLastError() ?-1 :0;
#elif _POSIX_C_SOURCE >= 199309L
/* prefer to use nanosleep() */
const struct timespec ts = {
ms / 1000, /* seconds */
(ms % 1000) * 1000 * 1000 /* nano seconds */
};
return nanosleep(&ts, NULL);
#elif _BSD_SOURCE || \
(_XOPEN_SOURCE >= 500 || \
_XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED) && \
!(_POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700)
/* else fallback to obsolte usleep() */
return usleep(1000 * ms);
#else
# error ("No millisecond sleep available for this platform!")
return -1;
#endif
}
Solution 2
I note that usleep is obsolescent but its a lot simpler than nanosleep. So I used it when I needed an enhanced sleep that would allow easy adjustment from seconds while debugging my scripts to milliseconds or zero for production.
This snooze function combines the advantages of sleep & usleep so that you can enter an int or float for your desired delay and 0.1 will sleep a 10th of a second while 3 will sleep for 3 seconds. 3.5 seconds is treated as 3 seconds.
Tested on Linux Mint 18.3 (Ubuntu 16.04.9) as C and C++ with gcc 5.4.0.
#include <unistd.h>
void snooze(double t) {(t > 1.0) ? sleep(t) : usleep(t*1000000);}
snooze(0.01); // call function to sleep for 10ms
For completeness, this is a nanosleep version. It's potentially more accurate than the usleep version and isn't threatened by obsolescence.
#include <time.h>
#include <math.h>
void snooze(double t) {
struct timespec req = {t, fmod(t, 1.0) * 1E9};
nanosleep(&req, NULL);
}
// struct timespec req = {t, fmod(t, 1.0) * 1E9};
// is equivalent to:
// struct timespec req = {0};
// req.tv_sec = t;
// req.tv_nsec = fmod(t, 1.0) * 1000000000L;
// NULL as value for *rem so no resumption after signal interrupts
snooze(1.99); // call for delay of 1.99 seconds
As suggested by @alk, the following versions return the called sleep function's error should one occur or 0 if successful. Defining the structure rem(aining) also permits resumption after a signal interrupt.
int snooze(double t) {
return (t > 1.0) ? sleep(t) : usleep(t*1000000);
}
int snooze(double t) {
struct timespec req = {t, fmod(t, 1.0) * 1E9};
struct timespec rem = {0, 0.0};
return nanosleep(&req, &rem);
}
Solution 3
Consider select
with empty FD sets and the timeout you want. From man select
:
Some code calls select() with all three sets empty, nfds zero, and a non-NULL timeout as a fairly portable way to sleep with subsecond precision.
Actually it might be the best solution for any non-Windows system.
Comments
-
rashok about 4 years
I have to write a C program which has to sleep for milliseconds, which has to run on various platforms like Windows, Linux, Solaris, HP-UX, IBM AIX, Vxworks, and Windriver Linux
- On Windows, the
Sleep
system call will work on milliseconds only. - On Linux,
sleep
will work on seconds;usleep
will perform on microseconds and it's available on Solaris also. - In Vxworks, I hope I can implement using
taskDelay
andsysClkRateSet
.
How can I achieve this millisecond sleep on HP-UX, IBM AIX and Wind River Linux?
- On Windows, the
-
rashok about 11 yearsThanks for your reply. currently we are using this only, in some platform
select
is not available. Like windriver linuxselect
is not available. -
Jonathan Leffler almost 7 yearsUnder POSIX 2004, the
usleep()
call was marked 'obsolescent', and it was removed from POSIX 2008. The preferred alternative isnanosleep()
. The general trend in POSIX is to preferstruct timespec
, which has nanosecond resolution, over alternatives such asstruct timeval
which has only microsecond resolution, orusleep()
which doesn't use a structure but works with microsecond resolution too. -
alk almost 7 years@JonathanLeffler: Thanks for notifying. Corrected.
-
alk about 6 yearsFor complete completeness you might want to take care of the value returned by the functions used.
-
John 9631 about 6 yearsThanks for the suggestion alk. I've added options.
-
Simon Kissane about 3 years@rashok select function exists on HP-UX and AIX. I am surprised by statement it doesn't exist on Wind River Linux. Wind River Linux is Linux, so how can it be missing the select system call? (or its newer replacements, newselect or pselect6).