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