diff options
| author | David du Colombier <0intro@gmail.com> | 2013-09-23 23:00:39 +0200 |
|---|---|---|
| committer | David du Colombier <0intro@gmail.com> | 2013-09-23 23:00:39 +0200 |
| commit | 6f4d00ee45693290fae042b27536b54f77b96acd (patch) | |
| tree | 60ad31bf16ed2000661c02345dd2a63851588a5d /src/cmd/fossil/periodic.c | |
| parent | fea86f063930ea187f1c77e93207ac8d39125520 (diff) | |
| download | plan9port-6f4d00ee45693290fae042b27536b54f77b96acd.tar.gz plan9port-6f4d00ee45693290fae042b27536b54f77b96acd.zip | |
fossil: import from plan 9
R=rsc
https://codereview.appspot.com/7988047
Diffstat (limited to 'src/cmd/fossil/periodic.c')
| -rw-r--r-- | src/cmd/fossil/periodic.c | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/src/cmd/fossil/periodic.c b/src/cmd/fossil/periodic.c new file mode 100644 index 00000000..8a0c2084 --- /dev/null +++ b/src/cmd/fossil/periodic.c @@ -0,0 +1,84 @@ +#include "stdinc.h" +#include "dat.h" +#include "fns.h" +#include "error.h" + +struct Periodic { + VtLock *lk; + int die; /* flag: quit if set */ + void (*f)(void*); /* call this each period */ + void *a; /* argument to f */ + int msec; /* period */ +}; + +static void periodicThread(void *a); + +Periodic * +periodicAlloc(void (*f)(void*), void *a, int msec) +{ + Periodic *p; + + p = vtMemAllocZ(sizeof(Periodic)); + p->lk = vtLockAlloc(); + p->f = f; + p->a = a; + p->msec = msec; + if(p->msec < 10) + p->msec = 10; + + vtThread(periodicThread, p); + return p; +} + +void +periodicKill(Periodic *p) +{ + if(p == nil) + return; + vtLock(p->lk); + p->die = 1; + vtUnlock(p->lk); +} + +static void +periodicFree(Periodic *p) +{ + vtLockFree(p->lk); + vtMemFree(p); +} + +static void +periodicThread(void *a) +{ + Periodic *p = a; + vlong t, ct, ts; /* times in ms. */ + + vtThreadSetName("periodic"); + + ct = nsec() / 1000000; + t = ct + p->msec; /* call p->f at or after this time */ + + for(;;){ + ts = t - ct; /* ms. to next cycle's start */ + if(ts > 1000) + ts = 1000; /* bound sleep duration */ + if(ts > 0) + sleep(ts); /* wait for cycle's start */ + + vtLock(p->lk); + if(p->die){ + vtUnlock(p->lk); + break; + } + ct = nsec() / 1000000; + if(t <= ct){ /* due to call p->f? */ + p->f(p->a); + ct = nsec() / 1000000; + while(t <= ct) /* advance t to future cycle start */ + t += p->msec; + } + vtUnlock(p->lk); + } + periodicFree(p); +} + |
