Mercurial > MadButterfly
diff src/timer.c @ 39:db2aa914e14b
timer for animation
author | Thinker K.F. Li <thinker@branda.to> |
---|---|
date | Wed, 06 Aug 2008 21:05:11 +0800 |
parents | |
children | 400b4b5db0dc |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/timer.c Wed Aug 06 21:05:11 2008 +0800 @@ -0,0 +1,131 @@ +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include "mb_timer.h" +#include "tools.h" + + +#define OK 0 +#define ERR -1 + +struct _mb_timer { + mbsec_t sec; + mbusec_t usec; + mb_tmo_hdlr hdlr; + void *arg; + mb_timer_t *next; +}; + +struct _mb_tman { + STAILQ(mb_timer_t) timers; + elmpool_t *timer_pool; +}; + +mb_tman_t *mb_tman_new(void) { + mb_tman_t *tman; + + tman = (mb_tman_t *)malloc(sizeof(mb_tman_t)); + if(tman == NULL) + return NULL; + + tman->timer_pool = elmpool_new(sizeof(mb_timer_t), 32); + if(tman->timer_pool == NULL) { + free(tman); + return NULL; + } + + STAILQ_INIT(tman->timers); + + return tman; +} + +void mb_tman_free(mb_tman_t *tman) { + elmpool_free(tman->timer_pool); + free(tman); +} + +mb_timer_t *mb_tman_timeout(mb_tman_t *tman, + mbsec_t sec, mbusec_t usec, + mb_tmo_hdlr hdlr, void *arg) { + mb_timer_t *timer, *visit, *last; + + timer = elmpool_elm_alloc(tman->timer_pool); + if(timer == NULL) + return NULL; + + timer->sec = sec; + timer->usec = usec; + timer->hdlr = hdlr; + timer->arg = arg; + + last = NULL; + for(visit = STAILQ_HEAD(tman->timers); + visit != NULL; + visit = STAILQ_NEXT(mb_timer_t, next, visit)) { + if(sec < visit->sec) + break; + if(sec == visit->sec && usec < visit->usec) + break; + last = visit; + } + + if(last == NULL) + STAILQ_INS(tman->timers, mb_timer_t, next, timer); + else if(visit == NULL) + STAILQ_INS_TAIL(tman->timers, mb_timer_t, next, timer); + else + STAILQ_INS_AFTER(mb_timer_t, next, timer, last); + + return timer; +} + +int mb_tman_remove(mb_tman_t *tman, mb_timer_t *timer) { + STAILQ_REMOVE(tman->timers, mb_timer_t, next, timer); + elmpool_elm_free(tman->timer_pool, timer); + + return OK; +} + +int mb_tman_next_timeout(mb_tman_t *tman, + mbsec_t now_sec, mbusec_t now_usec, + mbsec_t *after_sec, mbusec_t *after_usec) { + mb_timer_t *timer; + + timer = STAILQ_HEAD(tman->timers); + if(timer == NULL) + return ERR; + + if(now_sec > timer->sec || + (now_sec == timer->usec && now_usec >= timer->usec)) { + *after_sec = 0; + *after_usec = 0; + return OK; + } + + *after_sec = timer->sec - now_sec; + if(now_usec > timer->usec) { + --*after_sec; + *after_usec = 1000000 + timer->usec - now_usec; + } else + *after_usec = timer->usec - now_usec; + + return OK; +} + +int mb_tman_handle_timeout(mb_tman_t *tman, + mbsec_t now_sec, mbusec_t now_usec) { + mb_timer_t *timer; + + while((timer = STAILQ_HEAD(tman->timers)) != NULL){ + if(now_sec < timer->sec || + (now_sec == timer->sec && now_usec < timer->usec)) + break; + timer->hdlr(timer->sec, timer->usec, + now_sec, now_usec, + timer->arg); + STAILQ_REMOVE(tman->timers, mb_timer_t, next, timer); + elmpool_elm_free(tman->timer_pool, timer); + } + + return OK; +}