blob: 634f975d8dd53388ad565fcf8d33223ab30f7ae7 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
#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(;;){
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);
}
|