Ways to implement a timer in a workflow in C

I have a workflow that receives work from a channel. Something like that

void *worker(void *param) { while (!work_done) { read(g_workfds[0], work, sizeof(work)); do_work(work); } } 

I need to implement a 1 second timer in the same thread as some work books. Here is what I mean:

 void *worker(void *param) { prev_uptime = get_uptime(); while (!work_done) { // set g_workfds[0] as non-block now_uptime = get_uptime(); if (now_uptime - prev_uptime > 1) { do_book_keeping(); prev_uptime = now_uptime; } n = poll(g_workfds[0], 1000); // Wait for 1 second else timeout if (n == 0) // timed out continue; read(g_workfds[0], work, sizeof(work)); do_work(work); // This can take more than 1 second also } } 

I use the system uptime, not the system time, because the system time can change while this thread is running. I was wondering if there is another better way to do this. I do not want to consider another thread. Using alarm() not an option since it is already being used by another thread in the same process. This happens in a Linux environment.

+1
source share
3 answers

I found a better way, but it is specific to Linux using the timerfd_create () system call. He takes care of changing the system time. The following is the 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 the extra time elapsed if do_work() is time consuming, which is quite useful since do_book_keeping() expects to be called every second.

+2
source

I agree that webby wrote in his answer. But there is one problem with his suggestion to use time instead of uptime. If the system time is updated "forward", it will work as intended. But if the system time is canceled, say, 30 seconds, then it will not keep the book for 30 seconds, since (now_time - prev_time) will be negative (if the unsigned type is not 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 units of less time than seconds.

In addition, adding code to detect a backward beat is not difficult.

+3
source

I found some strange things in your code ...

poll () has 3 arguments, you pass 2, the second arg is the number of structures that you pass in the struct array of the first parameter, the third parameter is a timeout.

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

Also, itโ€™s good for me that a workaround is not the best, of course, but itโ€™s normal without involving another thread or alarm (), etc. You use time, not uptime, this can lead to one error if the system date is changed, but then it continues to work, as it will be updated and will continue to wait 1 second, regardless of time.

0
source

All Articles