Blob


1 #include "stdinc.h"
2 #include "dat.h"
3 #include "fns.h"
4 #include "error.h"
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 };
14 static void periodicThread(void *a);
16 Periodic *
17 periodicAlloc(void (*f)(void*), void *a, int msec)
18 {
19 Periodic *p;
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;
28 proccreate(periodicThread, p, STACK);
29 return p;
30 }
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 }
42 static void
43 periodicFree(Periodic *p)
44 {
45 vtfree(p);
46 }
48 static void
49 periodicThread(void *a)
50 {
51 Periodic *p = a;
52 vlong t, ct, ts; /* times in ms. */
54 threadsetname("periodic");
56 ct = nsec() / 1000000;
57 t = ct + p->msec; /* call p->f at or after this time */
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 */
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 }