POSIX.1-2001 standard defines function nanosleep()
, which is perfect for this. Unlike sleep()
and usleep()
, nanosleep()
does not interfere with signals.
Current Linux C libraries tend to implement usleep()
as a wrapper around nanosleep()
, however. You can see this if you strace
a test program (say, run strace /bin/sleep 1
).
However, as nanosleep()
is part of POSIX.1-2001 standard, it is definitely recommended.
For example:
#define _POSIX_C_SOURCE 200112L
#include <time.h>
#include <errno.h>
/* Sleep; returns un-slept (leftover) time.
*/
double dsleep(const double seconds)
{
const long sec = (long)seconds;
const long nsec = (long)((seconds - (double)sec) * 1e9);
struct timespec req, rem;
if (sec < 0L)
return 0.0;
if (sec == 0L && nsec <= 0L)
return 0.0;
req.tv_sec = sec;
if (nsec <= 0L)
req.tv_nsec = 0L;
else
if (nsec <= 999999999L)
req.tv_nsec = nsec;
else
req.tv_nsec = 999999999L;
rem.tv_sec = 0;
rem.tv_nsec = 0;
if (nanosleep(&req, &rem) == -1) {
if (errno == EINTR)
return (double)rem.tv_sec + (double)rem.tv_nsec / 1000000000.0;
else
return seconds;
} else
return 0.0;
}
Most of the logic above is to make sure (regardless of floating-point rounding mode et cetera) that the nanoseconds field is always within [0, 999999999], inclusive, and to make it safe to call it with negative values (in which case it'll just return zero).
If you want to specify the duration in integer milliseconds, you could use
#define _POSIX_C_SOURCE 200112L
#include <time.h>
#include <errno.h>
/* Sleep; returns un-slept (leftover) time.
*/
long msleep(const long ms)
{
struct timespec req, rem;
if (ms <= 0L)
return 0L;
req.tv_sec = ms / 1000L;
req.tv_nsec = (ms % 1000L) * 1000000L;
rem.tv_sec = 0;
rem.tv_nsec = 0;
if (nanosleep(&req, &rem) == -1) {
if (errno == EINTR)
return (long)rem.tv_sec * 1000L + rem.tv_nsec / 1000000L;
else
return ms;
} else
return 0L;
}
It is not necessary to zero out rem
, above, but written this way, these two functions are extremely robust, even against an occasional system hiccup or library bug.