plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

periodic.c (1355B)


      1 #include "stdinc.h"
      2 #include "dat.h"
      3 #include "fns.h"
      4 #include "error.h"
      5 
      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 };
     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 = vtmallocz(sizeof(Periodic));
     22 	p->f = f;
     23 	p->a = a;
     24 	p->msec = msec;
     25 	if(p->msec < 10)
     26 		p->msec = 10;
     27 
     28 	proccreate(periodicThread, p, STACK);
     29 	return p;
     30 }
     31 
     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 }
     41 
     42 static void
     43 periodicFree(Periodic *p)
     44 {
     45 	vtfree(p);
     46 }
     47 
     48 static void
     49 periodicThread(void *a)
     50 {
     51 	Periodic *p = a;
     52 	vlong t, ct, ts;		/* times in ms. */
     53 
     54 	threadsetname("periodic");
     55 
     56 	ct = nsec() / 1000000;
     57 	t = ct + p->msec;		/* call p->f at or after this time */
     58 
     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 */
     65 
     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 }