xref: /plan9/sys/src/cmd/fossil/periodic.c (revision ec59a3ddbfceee0efe34584c2c9981a5e5ff1ec4)
1 #include "stdinc.h"
2 #include "dat.h"
3 #include "fns.h"
4 #include "error.h"
5 
6 struct Periodic {
7 	VtLock *lk;
8 	int die;
9 	void (*f)(void*);
10 	void *a;
11 	int msec;
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 = vtMemAllocZ(sizeof(Periodic));
22 	p->lk = vtLockAlloc();
23 	p->f = f;
24 	p->a = a;
25 	p->msec = msec;
26 	if(p->msec < 10)
27 		p->msec = 10;
28 
29 	vtThread(periodicThread, p);
30 	return p;
31 }
32 
33 void
34 periodicKill(Periodic *p)
35 {
36 	if(p == nil)
37 		return;
38 	vtLock(p->lk);
39 	p->die = 1;
40 	vtUnlock(p->lk);
41 }
42 
43 static void
44 periodicFree(Periodic *p)
45 {
46 	vtLockFree(p->lk);
47 	vtMemFree(p);
48 }
49 
50 static void
51 periodicThread(void *a)
52 {
53 	Periodic *p = a;
54 	double t, ct, ts;
55 
56 	vtThreadSetName("periodic");
57 
58 	ct = nsec()*1e-6;
59 	t = ct + p->msec;
60 
61 	for(;;){
62 		/* skip missed */
63 		while(t <= ct)
64 			t += p->msec;
65 
66 		ts = t - ct;
67 		if(ts > 1000)
68 			ts = 1000;
69 		sleep(ts);
70 		ct = nsec()*1e-6;
71 		vtLock(p->lk);
72 		if(p->die){
73 			vtUnlock(p->lk);
74 			break;
75 		}
76 		if(t <= ct){
77 			p->f(p->a);
78 			t += p->msec;
79 		}
80 		vtUnlock(p->lk);
81 	}
82 	periodicFree(p);
83 }
84 
85