xref: /plan9/sys/src/cmd/fossil/periodic.c (revision 7fd2696ac38c1e0929802fd9633fa59b7bcc7c21)
15e96a66cSDavid du Colombier #include "stdinc.h"
25e96a66cSDavid du Colombier #include "dat.h"
35e96a66cSDavid du Colombier #include "fns.h"
45e96a66cSDavid du Colombier #include "error.h"
55e96a66cSDavid du Colombier 
65e96a66cSDavid du Colombier struct Periodic {
75e96a66cSDavid du Colombier 	VtLock *lk;
8*7fd2696aSDavid du Colombier 	int die;		/* flag: quit if set */
9*7fd2696aSDavid du Colombier 	void (*f)(void*);	/* call this each period */
10*7fd2696aSDavid du Colombier 	void *a;		/* argument to f */
11*7fd2696aSDavid du Colombier 	int msec;		/* period */
125e96a66cSDavid du Colombier };
135e96a66cSDavid du Colombier 
145e96a66cSDavid du Colombier static void periodicThread(void *a);
155e96a66cSDavid du Colombier 
165e96a66cSDavid du Colombier Periodic *
periodicAlloc(void (* f)(void *),void * a,int msec)175e96a66cSDavid du Colombier periodicAlloc(void (*f)(void*), void *a, int msec)
185e96a66cSDavid du Colombier {
195e96a66cSDavid du Colombier 	Periodic *p;
205e96a66cSDavid du Colombier 
215e96a66cSDavid du Colombier 	p = vtMemAllocZ(sizeof(Periodic));
225e96a66cSDavid du Colombier 	p->lk = vtLockAlloc();
235e96a66cSDavid du Colombier 	p->f = f;
245e96a66cSDavid du Colombier 	p->a = a;
255e96a66cSDavid du Colombier 	p->msec = msec;
265e96a66cSDavid du Colombier 	if(p->msec < 10)
275e96a66cSDavid du Colombier 		p->msec = 10;
285e96a66cSDavid du Colombier 
295e96a66cSDavid du Colombier 	vtThread(periodicThread, p);
305e96a66cSDavid du Colombier 	return p;
315e96a66cSDavid du Colombier }
325e96a66cSDavid du Colombier 
335e96a66cSDavid du Colombier void
periodicKill(Periodic * p)345e96a66cSDavid du Colombier periodicKill(Periodic *p)
355e96a66cSDavid du Colombier {
365e96a66cSDavid du Colombier 	if(p == nil)
375e96a66cSDavid du Colombier 		return;
385e96a66cSDavid du Colombier 	vtLock(p->lk);
395e96a66cSDavid du Colombier 	p->die = 1;
405e96a66cSDavid du Colombier 	vtUnlock(p->lk);
415e96a66cSDavid du Colombier }
425e96a66cSDavid du Colombier 
435e96a66cSDavid du Colombier static void
periodicFree(Periodic * p)445e96a66cSDavid du Colombier periodicFree(Periodic *p)
455e96a66cSDavid du Colombier {
465e96a66cSDavid du Colombier 	vtLockFree(p->lk);
475e96a66cSDavid du Colombier 	vtMemFree(p);
485e96a66cSDavid du Colombier }
495e96a66cSDavid du Colombier 
505e96a66cSDavid du Colombier static void
periodicThread(void * a)515e96a66cSDavid du Colombier periodicThread(void *a)
525e96a66cSDavid du Colombier {
535e96a66cSDavid du Colombier 	Periodic *p = a;
54*7fd2696aSDavid du Colombier 	vlong t, ct, ts;		/* times in ms. */
555e96a66cSDavid du Colombier 
565e96a66cSDavid du Colombier 	vtThreadSetName("periodic");
575e96a66cSDavid du Colombier 
58*7fd2696aSDavid du Colombier 	ct = nsec() / 1000000;
59*7fd2696aSDavid du Colombier 	t = ct + p->msec;		/* call p->f at or after this time */
605e96a66cSDavid du Colombier 
615e96a66cSDavid du Colombier 	for(;;){
62*7fd2696aSDavid du Colombier 		ts = t - ct;		/* ms. to next cycle's start */
635e96a66cSDavid du Colombier 		if(ts > 1000)
64*7fd2696aSDavid du Colombier 			ts = 1000;	/* bound sleep duration */
65*7fd2696aSDavid du Colombier 		if(ts > 0)
66*7fd2696aSDavid du Colombier 			sleep(ts);	/* wait for cycle's start */
67*7fd2696aSDavid du Colombier 
685e96a66cSDavid du Colombier 		vtLock(p->lk);
695e96a66cSDavid du Colombier 		if(p->die){
705e96a66cSDavid du Colombier 			vtUnlock(p->lk);
715e96a66cSDavid du Colombier 			break;
725e96a66cSDavid du Colombier 		}
73*7fd2696aSDavid du Colombier 		ct = nsec() / 1000000;
74*7fd2696aSDavid du Colombier 		if(t <= ct){		/* due to call p->f? */
755e96a66cSDavid du Colombier 			p->f(p->a);
76*7fd2696aSDavid du Colombier 			ct = nsec() / 1000000;
77*7fd2696aSDavid du Colombier 			while(t <= ct)	/* advance t to future cycle start */
785e96a66cSDavid du Colombier 				t += p->msec;
795e96a66cSDavid du Colombier 		}
805e96a66cSDavid du Colombier 		vtUnlock(p->lk);
815e96a66cSDavid du Colombier 	}
825e96a66cSDavid du Colombier 	periodicFree(p);
835e96a66cSDavid du Colombier }
845e96a66cSDavid du Colombier 
85