1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
|
/* Copyright ©2008 Kris Maglione <fbsdaemon@gmail.com>
* See LICENSE file for license details.
*/
#include <assert.h>
#include <stdlib.h>
#include <sys/time.h>
#include "ixp_local.h"
/* This really needn't be threadsafe, as it has little use in
* threaded programs, but it is, nonetheless.
*/
static long lastid = 1;
/**
* Function: ixp_msec
*
* Returns:
* Returns the time since the Epoch in milliseconds.
* Be aware that this may overflow.
*/
long
ixp_msec(void) {
timeval tv;
if(gettimeofday(&tv, 0) < 0)
return -1;
return tv.tv_sec*1000 + tv.tv_usec/1000;
}
/**
* Function: ixp_settimer
*
* Params:
* msec - The timeout in milliseconds.
* fn - The function to call after P<msec> milliseconds
* have elapsed.
* aux - An arbitrary argument to pass to P<fn> when it
* is called.
*
* Initializes a callback-based timer to be triggerred after
* P<msec> milliseconds. The timer is passed its id number
* and the value of P<aux>.
*
* Returns:
* Returns the new timer's unique id number.
*/
long
ixp_settimer(IxpServer *s, long msec, void (*fn)(long, void*), void *aux) {
Timer **tp;
Timer *t;
long time;
time = ixp_msec();
if(time == -1)
return -1;
msec += time;
t = emallocz(sizeof *t);
thread->lock(&s->lk);
t->id = lastid++;
t->msec = msec;
t->fn = fn;
t->aux = aux;
for(tp=&s->timer; *tp; tp=&tp[0]->link)
if(tp[0]->msec < msec)
break;
t->link = *tp;
*tp = t;
thread->unlock(&s->lk);
return t->id;
}
/**
* Function: ixp_unsettimer
*
* Params:
* id - The id number of the timer to void.
*
* Voids the timer identified by P<id>.
*
* Returns:
* Returns true if a timer was stopped, false
* otherwise.
*/
int
ixp_unsettimer(IxpServer *s, long id) {
Timer **tp;
Timer *t;
thread->lock(&s->lk);
for(tp=&s->timer; (t=*tp); tp=&t->link)
if(t->id == id)
break;
if(t) {
*tp = t->link;
free(t);
}
thread->unlock(&s->lk);
return t != nil;
}
/**
* Function: ixp_nexttimer
*
* Triggers any timers whose timeouts have ellapsed. This is
* primarilly intended to be called from libixp's select
* loop.
*
* Returns:
* Returns the number of milliseconds until the next
* timer's timeout.
*/
long
ixp_nexttimer(IxpServer *s) {
Timer *t;
long time, ret;
SET(time);
thread->lock(&s->lk);
while((t = s->timer)) {
time = ixp_msec();
if(t->msec > time)
break;
s->timer = t->link;
thread->unlock(&s->lk);
t->fn(t->id, t->aux);
free(t);
thread->lock(&s->lk);
}
ret = 0;
if(t)
ret = t->msec - time;
thread->unlock(&s->lk);
return ret;
}
|