#include #include #include #include #include #include #include "monitor.h" #include "me.h" struct mon_time_entry { void *(*callback)(void *); void *args; int flags; time_t time; int iter; int delay; struct mon_time_entry *next; struct mon_time_entry *prev; }; static void *mon_time_run(void *args); static void mon_time_dump(void); static pthread_t t; static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER; static struct mon_time_entry *list = NULL; static int running = 0; static void *mon_time_run(void *args) { struct mon_time_entry *p, *e; time_t now; pthread_t ct; while(1) { pthread_mutex_lock(&m); if(!list) { running = 0; pthread_mutex_unlock(&m); return NULL; } now = time(NULL); p = list; while(p) { if(p->time <= now) { pthread_create(&ct, NULL, p->callback, p->args); pthread_detach(ct); if((p->flags & MON_FLAG_PERM) && (!p->iter || (p->iter-- > 1))) { p->time = now + p->delay; p = p->next; } else { if(p == list) list = p->next; if(p->next) p->next->prev = p->prev; if(p->prev) p->prev->next = p->next; e = p; p = p->next; free(e); } } else { p = p->next; } } mon_time_dump(); pthread_mutex_unlock(&m); sleep(1); } } void mon_time_start(void *args) { pthread_mutex_lock(&m); if(!running) if(!pthread_create(&t, NULL, mon_time_run, NULL)) running = 1; pthread_mutex_unlock(&m); } void *mon_time_addwatch(void *(*callback)(void *), void *args, int flags, ...) { struct mon_time_entry *p = NULL; va_list va; pthread_mutex_lock(&m); do { if(!list) { if(!(list = malloc(sizeof(struct mon_time_entry)))) break; list->prev = NULL; p = list; } else { for(p = list; p->next; p = p->next); if(!(p->next = malloc(sizeof(struct mon_time_entry)))) break; p->next->prev = p; p = p->next; } p->next = NULL; p->callback = callback; p->args = args; p->flags = flags; va_start(va, flags); p->time = va_arg(va, int); if((p->delay = va_arg(va, int)) < 1) p->delay = 1; if((p->iter = va_arg(va, int)) < 0) p->iter = 0; va_end(va); if(!running) if(!pthread_create(&t, NULL, mon_time_run, NULL)) running = 1; } while(0); mon_time_dump(); pthread_mutex_unlock(&m); return p; } void mon_time_delwatch(void *entry) { struct mon_time_entry *p = NULL, *e = (struct mon_time_entry *)entry; if(!list || !e) return; pthread_mutex_lock(&m); for(p = list; p && (p != e); p = p->next); if(p) { if(p == list) list = p->next; if(p->next) p->next->prev = p->prev; if(p->prev) p->prev->next = p->next; free(p); } pthread_mutex_unlock(&m); return; } void mon_time_dump(void) { #if 0 struct mon_time_entry *p = NULL; debugme("\n--- TIME MONITOR LIST ---\n"); for(p = list; p; p = p->next) debugme("- %u %u (at %p)\n", (unsigned int)p->time, p->iter, (void *)p); debugme("\n"); #endif return; } .