periodic.c (1355B)
1 #include "stdinc.h" 2 #include "dat.h" 3 #include "fns.h" 4 #include "error.h" 5 6 struct Periodic { 7 QLock lk; 8 int die; /* flag: quit if set */ 9 void (*f)(void*); /* call this each period */ 10 void *a; /* argument to f */ 11 int msec; /* period */ 12 }; 13 14 static void periodicThread(void *a); 15 16 Periodic * 17 periodicAlloc(void (*f)(void*), void *a, int msec) 18 { 19 Periodic *p; 20 21 p = vtmallocz(sizeof(Periodic)); 22 p->f = f; 23 p->a = a; 24 p->msec = msec; 25 if(p->msec < 10) 26 p->msec = 10; 27 28 proccreate(periodicThread, p, STACK); 29 return p; 30 } 31 32 void 33 periodicKill(Periodic *p) 34 { 35 if(p == nil) 36 return; 37 qlock(&p->lk); 38 p->die = 1; 39 qunlock(&p->lk); 40 } 41 42 static void 43 periodicFree(Periodic *p) 44 { 45 vtfree(p); 46 } 47 48 static void 49 periodicThread(void *a) 50 { 51 Periodic *p = a; 52 vlong t, ct, ts; /* times in ms. */ 53 54 threadsetname("periodic"); 55 56 ct = nsec() / 1000000; 57 t = ct + p->msec; /* call p->f at or after this time */ 58 59 for(;;){ 60 ts = t - ct; /* ms. to next cycle's start */ 61 if(ts > 1000) 62 ts = 1000; /* bound sleep duration */ 63 if(ts > 0) 64 sleep(ts); /* wait for cycle's start */ 65 66 qlock(&p->lk); 67 if(p->die){ 68 qunlock(&p->lk); 69 break; 70 } 71 ct = nsec() / 1000000; 72 if(t <= ct){ /* due to call p->f? */ 73 p->f(p->a); 74 ct = nsec() / 1000000; 75 while(t <= ct) /* advance t to future cycle start */ 76 t += p->msec; 77 } 78 qunlock(&p->lk); 79 } 80 periodicFree(p); 81 }