acme9k/time.c
Derek Stevens 2908f1ff9b add active tick indication; v9001-a02
window tag/body with keyboard focus will render tick in hilighted text color; doesn't work yet for column/row tags
2022-02-21 22:53:04 -07:00

107 lines
2.1 KiB
C

#include <u.h>
#include <libc.h>
#include <draw.h>
#include <thread.h>
#include <cursor.h>
#include <mouse.h>
#include <keyboard.h>
#include "libframe/frame.h"
#include <fcall.h>
#include <plumb.h>
#include <libsec.h>
#include "dat.h"
#include "fns.h"
static Channel* ctimer; /* chan(Timer*)[100] */
static Timer* timer;
static uint msec(void) { return nsec() / 1000000; }
void timerstop(Timer* t) {
t->next = timer;
timer = t;
}
void timercancel(Timer* t) { t->cancel = TRUE; }
static void timerproc(void* v) {
int i, nt, na, dt, del;
Timer **t, *x;
uint old, new;
USED(v);
threadsetname("timerproc");
rfork(RFFDG);
t = nil;
na = 0;
nt = 0;
old = msec();
for (;;) {
sleep(10); /* longer sleeps here delay recv on ctimer, but 10ms should not
be noticeable */
new = msec();
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;
del = FALSE;
if (x->cancel) {
timerstop(x);
del = TRUE;
} else if (x->dt <= 0) {
/*
* avoid possible deadlock if client is
* now sending on ctimer
*/
if (nbsendul(x->c, 0) > 0)
del = TRUE;
}
if (del) {
memmove(&t[i], &t[i + 1], (nt - i - 1) * sizeof t[0]);
--nt;
--i;
}
}
if (nt == 0) {
x = recvp(ctimer);
gotit:
if (nt == na) {
na += 10;
t = realloc(t, na * sizeof(Timer*));
if (t == nil)
error("timer realloc failed");
}
t[nt++] = x;
old = msec();
}
if (nbrecv(ctimer, &x) > 0)
goto gotit;
}
}
void timerinit(void) {
ctimer = chancreate(sizeof(Timer*), 100);
chansetname(ctimer, "ctimer");
proccreate(timerproc, nil, STACK);
}
Timer* timerstart(int dt) {
Timer* t;
t = timer;
if (t)
timer = timer->next;
else {
t = emalloc(sizeof(Timer));
t->c = chancreate(sizeof(int), 0);
chansetname(t->c, "tc%p", t->c);
}
t->next = nil;
t->dt = dt;
t->cancel = FALSE;
sendp(ctimer, t);
return t;
}