forsyth20121205-174063a80cc13 years agoHistory
99 lines · 1.8 KB · Brainfuck
RawDownload
implement Timers; include "sys.m";	sys:	Sys; include "timers.m"; timerin: chan of ref Timer; init(minms: int): int{	sys = load Sys Sys->PATH;	timerin = chan[20] of ref Timer;	if(minms <= 0)		minms = 1;	pid := chan of int;	spawn timeproc(timerin, minms, pid);	return <-pid;} shutdown(){	if(timerin != nil)		timerin <-= nil;}	 Timer.start(dt: int): ref Timer{	t := ref Timer(dt, chan[1] of int);	timerin <-= t;	return t;} Timer.stop(t: self ref Timer){	# this is safe, because only Timer.stop sets t.timeout and timeproc only fetches it	t.timeout = nil;}			timeproc(req: chan of ref Timer, msec: int, pid: chan of int){	pending: list of ref Timer; 	pid <-= sys->pctl(Sys->NEWFD|Sys->NEWNS|Sys->NEWENV, nil);	# same pgrp	old := sys->millisec();Work:	for(;;){		if(pending == nil){			if((t := <-req) == nil)				break Work;			pending = t :: pending;			old = sys->millisec();		}else{			# check quickly for new requests		Check:			for(;;) alt{			t := <-req =>				if(t == nil)					break Work;				pending = t :: pending;			* =>				break Check;			}		}		sys->sleep(msec);		new := sys->millisec();		dt := new-old;		old = new;		if(dt < 0)			continue;	# millisec counter wrapped		ticked := 0;		for(l := pending; l != nil; l = tl l)			if(((hd l).dt -= dt) <= 0)				ticked = 1;		if(ticked){			l = pending;			pending = nil;			for(; l != nil; l = tl l){				t := hd l;				if(t.dt > 0 || !notify(t))					pending = t :: pending;			}		}	}	# shut down: attempt to clear pending requests	for(; pending != nil; pending = tl pending)		notify(hd pending);} notify(t: ref Timer): int{	# copy to c to avoid race with Timer.stop	if((c := t.timeout) == nil)		return 1;	# cancelled; consider it done	alt{	c <-= 1 => return 1;	* => return 0;	}}