Mercurial > MadButterfly
view src/timer.c @ 1479:92a8497d0361
Make FSM editor scrollable
author | Thinker K.F. Li <thinker@codemud.net> |
---|---|
date | Wed, 27 Apr 2011 15:41:47 +0800 |
parents | 7ccc094bdbe5 |
children |
line wrap: on
line source
// -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 4; -*- // vim: sw=4:ts=8:sts=4 #include <stdio.h> #include <stdint.h> #include <stdlib.h> #include <string.h> #include "mb_timer.h" #include "mb_tools.h" #include "mb_backend.h" #define OK 0 #define ERR -1 struct _mb_timer { mb_timeval_t tmo; 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, const mb_timeval_t *tmo, mb_tmo_hdlr hdlr, void *arg) { mb_timer_t *timer, *visit, *last; timer = elmpool_elm_alloc(tman->timer_pool); if(timer == NULL) return NULL; MB_TIMEVAL_CP(&timer->tmo, tmo); 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(MB_TIMEVAL_LATER(&visit->tmo, tmo) || MB_TIMEVAL_EQ(&visit->tmo, tmo)) 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; } /*! \brief Get how long to next timeout from this monent. * * \return 0 for having next timeout, -1 for not more timeout. */ int mb_tman_next_timeout(mb_tman_t *tman, const mb_timeval_t *now, mb_timeval_t *tmo_after) { mb_timer_t *timer; timer = STAILQ_HEAD(tman->timers); if(timer == NULL) return ERR; if(!MB_TIMEVAL_LATER(&timer->tmo, now)) { memset(tmo_after, 0, sizeof(mb_timeval_t)); return OK; } MB_TIMEVAL_CP(tmo_after, &timer->tmo); MB_TIMEVAL_DIFF(tmo_after, now); return OK; } int mb_tman_handle_timeout(mb_tman_t *tman, mb_timeval_t *now) { mb_timer_t *timer; while((timer = STAILQ_HEAD(tman->timers)) != NULL){ if(MB_TIMEVAL_LATER(&timer->tmo, now)) break; timer->hdlr(&timer->tmo, now, timer->arg); STAILQ_REMOVE(tman->timers, mb_timer_t, next, timer); elmpool_elm_free(tman->timer_pool, timer); } return OK; } /*! \defgroup tman_timer_man Timer manager based on mb_tman_t. * * This implmentation of timer manager is based on mb_tman_t. * @{ */ struct _tman_timer_man { mb_timer_man_t timer_man; mb_tman_t *tman; }; static int _tman_timer_man_timeout(struct _mb_timer_man *tm_man, mb_timeval_t *tmout, mb_timer_cb_t cb, void *data); static void _tman_timer_man_remove(struct _mb_timer_man *tm_man, int tm_hdl); static mb_timer_man_t *_tman_timer_fact_new(void); static void _tman_timer_fact_free(mb_timer_man_t *timer_man); static struct _tman_timer_man _tman_default_timer_man = { {_tman_timer_man_timeout, _tman_timer_man_remove}, NULL }; mb_timer_factory_t tman_timer_factory = { _tman_timer_fact_new, _tman_timer_fact_free }; /*! \brief Content of a timeout request. * * This is only used by internal of X support. This data structure * carry information to adopt mb_tman_t to mb_timer_man_t. */ struct _tman_timeout_data { mb_timer_t *timer; /*!< Handle returned by mb_tman_timeout() */ mb_timer_cb_t cb; /*!< Real callback function */ void *data; /*!< data for real callback */ }; static void _tman_tmo_hdlr(const mb_timeval_t *tmo, const mb_timeval_t *now, void *arg) { struct _tman_timeout_data *data = (struct _tman_timeout_data *)arg; data->cb((int)data, tmo, now, data->data); } static int _tman_timer_man_timeout(struct _mb_timer_man *tm_man, mb_timeval_t *tmout, /* timeout (wall time) */ mb_timer_cb_t cb, void *data) { struct _tman_timer_man *timer_man = (struct _tman_timer_man *)tm_man; mb_timer_t *timer; struct _tman_timeout_data *tmout_data; tmout_data = O_ALLOC(struct _tman_timeout_data); tmout_data->cb = cb; tmout_data->data = data; timer = mb_tman_timeout(timer_man->tman, tmout, _tman_tmo_hdlr, tmout_data); if(timer == NULL) return ERR; tmout_data->timer = timer; return (int)tmout_data; } static void _tman_timer_man_remove(struct _mb_timer_man *tm_man, int tm_hdl) { struct _tman_timer_man *timer_man = (struct _tman_timer_man *)tm_man; struct _tman_timeout_data *tmout_data = (struct _tman_timeout_data *)tm_hdl; mb_tman_remove(timer_man->tman, tmout_data->timer); free(tmout_data); } static mb_timer_man_t * _tman_timer_fact_new(void) { if(_tman_default_timer_man.tman == NULL) _tman_default_timer_man.tman = mb_tman_new(); return (mb_timer_man_t *)&_tman_default_timer_man; } static void _tman_timer_fact_free(mb_timer_man_t *timer_man) { } mb_tman_t * tman_timer_man_get_tman(mb_timer_man_t *tm_man) { struct _tman_timer_man *timer_man = (struct _tman_timer_man *)tm_man; return timer_man->tman; } /* @} */