ref: babf901b4a508c3ec5d1f89655f10377bbdf9637
dir: /appl/acme/time.b/
implement Timerm;
include "common.m";
sys : Sys;
acme : Acme;
utils : Utils;
dat : Dat;
millisec : import sys;
Timer : import dat;
init(mods : ref Dat->Mods)
{
sys = mods.sys;
acme = mods.acme;
utils = mods.utils;
dat = mods.dat;
}
ctimer : chan of ref Timer;
timeproc()
{
i, nt, na, dt : int;
x : ref Timer;
t : array of ref Timer;
old, new : int;
acme->timerpid = sys->pctl(0, nil);
sys->pctl(Sys->FORKFD, nil);
t = array[10] of ref Timer;
na = 10;
nt = 0;
old = millisec();
for(;;){
if (nt == 0) { # don't waste cpu time
x = <-ctimer;
t[nt++] = x;
old = millisec();
}
sys->sleep(1); # will sleep minimum incr
new = millisec();
dt = new-old;
old = new;
if(dt < 0) # timer wrapped; go around, losing a tick
continue;
for(i=0; i<nt; i++){
x = t[i];
x.dt -= dt;
if(x.dt <= 0){
#
# avoid possible deadlock if client is
# now sending on ctimer
#
alt {
x.c <-= 0 =>
t[i:] = t[i+1:nt];
t[nt-1] = nil;
nt--;
i--;
* =>
;
}
}
}
gotone := 1;
while (gotone) {
alt {
x = <-ctimer =>
if (nt == na) {
ot := t;
t = array[na+10] of ref Timer;
t[0:] = ot[0:na];
ot = nil;
na += 10;
}
t[nt++] = x;
old = millisec();
* =>
gotone = 0;
}
}
}
}
timerinit()
{
ctimer = chan of ref Timer;
spawn timeproc();
}
#
# timeralloc() and timerfree() don't lock, so can only be
# called from the main proc.
#
timer : ref Timer;
timerstart(dt : int) : ref Timer
{
t : ref Timer;
t = timer;
if(t != nil)
timer = timer.next;
else{
t = ref Timer;
t.c = chan of int;
}
t.next = nil;
t.dt = dt;
ctimer <-= t;
return t;
}
timerstop(t : ref Timer)
{
t.next = timer;
timer = t;
}
timerwaittask(timer : ref Timer)
{
<-(timer.c);
timerstop(timer);
}