#include #include #include #include #include "timer.h" typedef unsigned long long timer_usec_t; typedef struct timer_entry *timer_entry_t; struct timer_entry { struct timer_entry *next; int id; int msec; timer_usec_t interval; struct { timer_handler_t handler; int arg; void *p; } callback; }; struct timer_list { timer_usec_t current; struct timer_entry *entry; }; static struct timer_list timer_list; static void sigalrm_handler(int val) { return; } static int settimer(timer_usec_t t) { #if 0 struct itimerval itimer; itimer.it_interval.tv_sec = 0; itimer.it_interval.tv_usec = 0; itimer.it_value.tv_sec = t / 1000000; itimer.it_value.tv_usec = t % 1000000; return setitimer(ITIMER_REAL, &itimer, NULL); #else return 0; #endif } int timer_init() { struct timeval tv; gettimeofday(&tv, NULL); timer_list.current = (timer_usec_t)tv.tv_sec * 1000000 + tv.tv_usec; timer_list.entry = NULL; signal(SIGALRM, sigalrm_handler); return 0; } static int _timer_add(struct timer_entry *entry) { timer_usec_t t; struct timer_entry **entryp; t = entry->msec * 1000; for (entryp = &timer_list.entry; *entryp; entryp = &((*entryp)->next)) { if (t < (*entryp)->interval) break; t -= (*entryp)->interval; } entry->interval = t; if (*entryp) (*entryp)->interval -= t; entry->next = *entryp; *entryp = entry; return 0; } int timer_expire() { struct timeval tv; timer_usec_t current, t; struct timer_entry *entry, *expired = NULL; int r; gettimeofday(&tv, NULL); current = (timer_usec_t)tv.tv_sec * 1000000 + tv.tv_usec; t = current - timer_list.current; while (timer_list.entry && timer_list.entry->interval <= t) { entry = timer_list.entry; timer_list.entry = entry->next; t -= entry->interval; r = entry->callback.handler(entry->callback.arg, entry->callback.p); if (r> 0) entry->msec = r; else if (r == 0) entry->msec = -1; entry->next = expired; expired = entry; } timer_list.current = current; if (timer_list.entry) { timer_list.entry->interval -= t; } entry = NULL; while (expired) { entry = expired; expired = expired->next; if (entry->msec < 0) free(entry); else _timer_add(entry); } if (entry && timer_list.entry) { settimer(timer_list.entry->interval); } return entry ? 1 : 0; } int timer_add(int id, int msec, timer_handler_t handler, int arg, void *p) { struct timer_entry *entry; entry = malloc(sizeof(*entry)); if (!entry) return -1; entry->id = id; entry->msec = msec; entry->callback.handler = handler; entry->callback.arg = arg; entry->callback.p = p; timer_expire(); _timer_add(entry); if (timer_list.entry == entry) { settimer(timer_list.entry->interval); } return id; } int timer_del(int id) { struct timer_entry *entry = NULL, **entryp; for (entryp = &timer_list.entry; *entryp; entryp = &((*entryp)->next)) { if ((*entryp)->id == id) { entry = *entryp; *entryp = entry->next; if (*entryp) { (*entryp)->interval += entry->interval; } free(entry); break; } } timer_expire(); return entry ? id : -1; } int timer_print() { struct timer_entry *entry; printf("TIMER LIST:\n"); for (entry = timer_list.entry; entry; entry = entry->next) { printf("\tid:%08x msec:%d interval:%lld handler:%p arg:%08x p:%p\n", entry->id, entry->msec, entry->interval, entry->callback.handler, entry->callback.arg, entry->callback.p); } return 0; }

AltStyle によって変換されたページ (->オリジナル) /