linux - How to create a non single-shot timer in C? -


i need use non single shot timer (such qtimer qt library) in c code embedded linux (by no single shot timer mean 1 triggers once ever x seconds indefinitely till "stop timer" called, not 1 triggers once or 1 blocks code while it's counting).

some libraries available me implement such timer using signal handlers, avoid using such system (i learned not best solution). know can emulate want single shot timers restarting timer (calling again) once it's finished, , acceptable solution (actually libraries talked work way), don't know how implement without blocking running code till timer triggered.

and 1 more thing: need capable of implementing more 1 of them (here signal handlers stop being viable solution afaik).

so how such solution? closes qt's qtimer has offer, better!

if need unspecified number of triggers @ varying intervals/times, dedicated timer thread (as described nneonneo in answer) has least number of pitfalls in experience.

timers limited resource (the number of timers available configurable, , varies system system, cannot make sweeping statements "i'm sure there's enough purposes").

signals interrupt blocking syscalls unless sa_restart flag used; there few exceptions (see man 7 signal, interruption of system calls , library functions signal handlers chapter details).


a dedicated timer thread built around 2 components:

  1. a queue, list, tree, or heap holding timer events

    a typical implementation needs know when next event occurs, min-heap or priority queue works quite well. i've found min-heap simple , robust implement, , efficient enough (o(log n) time complexity both inserts , deletes); using absolute times (using clock_monotonic in linux) events keys.

    note if use timer events timeouts, you'll need make sure cancelling event efficient. in normal operation, timeouts rare, web server cancel timeouts sets, without of them ever triggering.

  2. a thread waits either next event, or thread inserting new timer event

    personally, use array hold min-heap of events, protected pthread_mutex_t, pthread_cond_t other threads signal on after adding new event. then, it's simple matter use pthread_cond_timedwait() wait/sleep either specified time, or until thread notifies of new event, whichever happens sooner.

    when next event occurs -- note due scheduling, might find more 1 separate event occur, might not wish sleep @ (but might still check if new events added) --, perform event. if event periodic, reinsert heap/queue, too, primed next time.

choosing how events performed important, , really, tricky bit. can use flags -- switching 0 nonzero safe in practice, if change not atomic, long don't rely on specific nonzero value --; can cause condition variable signaled or broadcast on; can post semaphore; can raise specific signal in specific thread (even empty signal handler cause blocking i/o calls interrupt, if handler installed without sa_restart flag; i've used i/o timeout quite successfully); can use __atomic or __sync modify value atomically if using gcc (or intel cc, pathscale, or portland group c compilers); , on.

if need specific function called, recommend using separate thread (or, if of work in application/program/game done in these timer events, thread pool) execute events. keeps timer thread simple , precise, while keeping resource use controlled. worker thread or thread pool should have fifo queue of events protected mutex , condition variable, timer thread can add each event queue , signal on condition variable notify (next) worker thread work available.

indeed, in couple of instances used other event action models, believe function worker model have been easier. if make worker functions take pointer (to structure), defined caller, have same signature, interface becomes quite straightforward implement, extremely powerful , versatile.

there 1 downside timer-thread plus worker-thread(s) approach, , (minimal) added latency. worker thread not work at appointed time, short while afterwards. however, if have worker thread current time, compare (un-adjusted) target time, , use statistic trigger events correspondingly prior target time, can typically take care of issue. (i have not verified, believe both qt , gtk+ toolkits continuously estimate latency in similar if not same manner.)

questions?


Comments

Popular posts from this blog

javascript - RequestAnimationFrame not working when exiting fullscreen switching space on Safari -

jsf - How to ajax update an item in the footer of a PrimeFaces dataTable? -

django - CSRF verification failed. Request aborted. CSRF cookie not set -