The offered answers show you that there are tools available in Boost to help you accomplish this. My late offering illustrates how to use setitimer()
, which is a POSIX facility for iterative timers.
You basically need a change like this:
while (1){
// wait until 200 ms boundary
// get a sample
}
With an iterative timer, the fired signal would interrupt any blocked signal call. So, you could just block on something forever. select
will do fine for that:
while (1){
int select_result = select(0, 0, 0, 0, 0);
assert(select_result < 0 && errno == EINTR);
// get a sample
}
To establish an interval timer for every 200 ms, use setitimer()
, passing in an appropriate interval. In the code below, we set an interval for 200 ms, where the first one fires 150 ms from now.
struct itimerval it = { { 0, 200000 }, { 0, 150000 } };
if (setitimer(ITIMER_REAL, &it, 0) != 0) {
perror("setitimer");
exit(EXIT_FAILURE);
}
Now, you just need to install a signal handler for SIGALRM
that does nothing, and the code is complete.
You can follow the link to see the completed example.
If it is possible for multiple signals to be fired during the program execution, then instead of relying on the interrupted system call, it is better to block on something that the SIGALRM
handler can wake up in a deterministic way. One possibility is to have the while
loop block on read
of the read end of a pipe. The signal handler can then write to the write end of that pipe.
void sigalarm_handler (int)
{
if (write(alarm_pipe[1], "", 1) != 1) {
char msg[] = "write: failed from sigalarm_handler\n";
write(2, msg, sizeof(msg)-1);
abort();
}
}
Follow the link to see the completed example.
alarm(2)
orualarm(3)
(part of POSIX, should be available everywhere) withgettimeofday(2)
, or perhapsusleep(3)
(this is Linux-only, AFAIK). But be careful, what a signal handler is allowed to do is very limited, seesignal(7)
. – Bezonian