libixp

git clone git://oldgit.suckless.org/libixp/
Log | Files | Refs | LICENSE

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