ref: 333ae58f37c2c8f79f7d7078283a30e42c4d7a27
dir: /periodic.c/
#include "stdinc.h" #include "dat.h" #include "fns.h" #include "error.h" struct Periodic { QLock lk; int die; /* flag: quit if set */ void (*f)(void*); /* call this each period */ void *a; /* argument to f */ int msec; /* period */ }; static void periodicThread(void *a); Periodic * periodicAlloc(void (*f)(void*), void *a, int msec) { Periodic *p; p = vtmallocz(sizeof(Periodic)); p->f = f; p->a = a; p->msec = msec; if(p->msec < 10) p->msec = 10; proccreate(periodicThread, p, STACK); return p; } void periodicKill(Periodic *p) { if(p == nil) return; qlock(&p->lk); p->die = 1; qunlock(&p->lk); } static void periodicFree(Periodic *p) { vtfree(p); } static void periodicThread(void *a) { Periodic *p = a; vlong t, ct, ts; /* times in ms. */ threadsetname("periodic"); ct = nsec() / 1000000; t = ct + p->msec; /* call p->f at or after this time */ for(;;){ if(t - ct > p->msec) /* time went backwards? */ t = ct + p->msec; ts = t - ct; /* ms. to next cycle's start */ if(ts > 1000) ts = 1000; /* bound sleep duration */ if(ts > 0) sleep(ts); /* wait for cycle's start */ qlock(&p->lk); if(p->die){ qunlock(&p->lk); break; } ct = nsec() / 1000000; if(t <= ct){ /* due to call p->f? */ p->f(p->a); ct = nsec() / 1000000; while(t <= ct) /* advance t to future cycle start */ t += p->msec; } qunlock(&p->lk); } periodicFree(p); }