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;
+}