Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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;		/* 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 = 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
	vlong t, ct, ts;		/* times in ms. */
55
 
56
	vtThreadSetName("periodic");
57
 
58
	ct = nsec() / 1000000;
59
	t = ct + p->msec;		/* call p->f at or after this time */
60
 
61
	for(;;){
62
		ts = t - ct;		/* ms. to next cycle's start */
63
		if(ts > 1000)
64
			ts = 1000;	/* bound sleep duration */
65
		if(ts > 0)
66
			sleep(ts);	/* wait for cycle's start */
67
 
68
		vtLock(p->lk);
69
		if(p->die){
70
			vtUnlock(p->lk);
71
			break;
72
		}
73
		ct = nsec() / 1000000;
74
		if(t <= ct){		/* due to call p->f? */
75
			p->f(p->a);
76
			ct = nsec() / 1000000;
77
			while(t <= ct)	/* advance t to future cycle start */
78
				t += p->msec;
79
		}
80
		vtUnlock(p->lk);
81
	}
82
	periodicFree(p);
83
}
84