ways of implementing timer in worker thread in C ways of implementing timer in worker thread in C unix unix

ways of implementing timer in worker thread in C


I agree with most of what webbi wrote in his answer. But there is one issue with his suggestion of using time instead of uptime. If the system time is updated "forward" it will work as intended. But if the system time is set back by say 30 seconds, then there will be no book keeping done for 30 seconds as (now_time - prev_time) will be negative (unless an unsigned type is used, in which case it will work anyway).

An alternative would be to use clock_gettime() with CLOCK_MONOTONIC as clockid ( http://linux.die.net/man/2/clock_gettime ). A bit messy if you don't need smaller time units than seconds.

Also, adding code to detect a backwards clock jump isn't hard either.


I have found a better way but it is Linux specific using timerfd_create() system call. It takes care of system time change. Following is possible psuedo code:

void *worker(void *param) {  int timerfd = timerfd_create(CLOCK_MONOTONIC, 0);  // Monotonic doesn't get affected by system time change  // set timerfd to non-block   timerfd_settime(timerfd, 1 second timer);     // timer starts   while (!work_done) {    // set g_workfds[0] as non-block    n = poll(g_workfds[0] and timerfd, 0); // poll on both pipe and timerfd and Wait indefinetly     if (timerfd is readable)        do_book_keeping();    if (g_workfds[0] is readable) {       read(g_workfds[0], work, sizeof(work));       do_work(work);   // This can take more than 1 second also    }  }}

It seems cleaner and read() on timerfd returns extra time elapsed in case do_work() takes long time which is quite useful as do_book_keeping() expects to get called every second.


I found some things weird in your code...

poll() has 3 args, you are passing 2, the second arg is the number of structs that you are passing in the struct array of first param, the third param is the timeout.

Reference: http://linux.die.net/man/2/poll

Besides that, it's fine for me that workaround, it's not the best of course, but it's fine without involving another thread or alarm(), etc.You use time and not uptime, it could cause you one error if the system date gets changed, but then it will continue working as it will be updated and continuing waiting for 1 sec, no matter what time is.