X-Git-Url: http://git.pk910.de/?p=NeonServV5.git;a=blobdiff_plain;f=src%2Ftimeq.c;h=ec9ea3e4017803440e5c5c63637e9b8aaa7ffbab;hp=4ee011eac05bf73e5245be63ab57c281923e3033;hb=HEAD;hpb=bb5692b9cbff069abbf9573c81e86c3cd2061ceb diff --git a/src/timeq.c b/src/timeq.c index 4ee011e..ec9ea3e 100644 --- a/src/timeq.c +++ b/src/timeq.c @@ -1,4 +1,4 @@ -/* timeq.c - NeonServ v5.3 +/* timeq.c - NeonServ v5.6 * Copyright (C) 2011-2012 Philipp Kreil (pk910) * * This program is free software: you can redistribute it and/or modify @@ -16,102 +16,134 @@ */ #include "timeq.h" +#include "IOHandler.h" +#include "tools.h" +#include "log.h" static struct timeq_entry *timeq_events; +#ifdef HAVE_THREADS +static int pthread_mutex_initialized = 0; +static pthread_mutex_t synchronized; +#endif -void timeq_tick() { - struct timeq_entry *entry, *next; - time_t now = time(0); - for(entry = timeq_events; entry; entry = next) { - if(entry->execute <= now) { - entry->callback(entry->data); - next = entry->next; - if(timeq_events == entry) - timeq_events = next; - free(entry); - } else - break; +static IOHANDLER_CALLBACK(timeq_callback) { + struct timeq_entry *entry = event->iofd->data; + switch(event->type) { + case IOEVENT_TIMEOUT: + if(entry->name) { + free(entry->name); + entry->name = NULL; + } + entry->callback(entry->data); + entry->iofd = NULL; + timeq_del(entry); + break; + default: + break; } } -struct timeq_entry* timeq_add(int seconds, timeq_callback_t *callback, void *data) { - time_t now = time(0); +struct timeq_entry* timeq_add(int seconds, int module_id, timeq_callback_t *callback, void *data) { + return timeq_uadd(seconds * 1000, module_id, callback, data); +} + +struct timeq_entry* timeq_uadd(int useconds, int module_id, timeq_callback_t *callback, void *data) { + struct timeval timeout; struct timeq_entry *entry = malloc(sizeof(*entry)); if (!entry) { - perror("malloc() failed"); + printf_log("main", LOG_ERROR, "%s:%d malloc() failed", __FILE__, __LINE__); return NULL; } - entry->execute = now + seconds; + #ifdef HAVE_THREADS + if(!pthread_mutex_initialized) { + THREAD_MUTEX_INIT(synchronized); + pthread_mutex_initialized = 1; + } + #endif + gettimeofday(&timeout, NULL); + SYNCHRONIZE(synchronized); + timeout.tv_usec += (useconds % 1000); + timeout.tv_sec += (useconds / 1000); + entry->iofd = iohandler_timer(timeout, timeq_callback); + entry->iofd->data = entry; + entry->module_id = module_id; entry->callback = callback; entry->data = data; entry->name = NULL; - struct timeq_entry *next, *prev = NULL; - for(next = timeq_events; next; next = next->next) { - if(next->execute >= entry->execute) - break; - else - prev = next; - } - if(prev == NULL) { - entry->next = timeq_events; - timeq_events = entry; - } else { - entry->next = next; - prev->next = entry; - } + entry->next = timeq_events; + entry->prev = NULL; + if(timeq_events) + timeq_events->prev = entry; + timeq_events = entry; + DESYNCHRONIZE(synchronized); return entry; } -struct timeq_entry* timeq_add_name(char *name, int seconds, timeq_callback_t *callback, void *data) { - struct timeq_entry *entry = timeq_add(seconds, callback, data); +struct timeq_entry* timeq_add_name(char *name, int seconds, int module_id, timeq_callback_t *callback, void *data) { + return timeq_uadd_name(name, seconds * 1000, module_id, callback, data); +} + +struct timeq_entry* timeq_uadd_name(char *name, int useconds, int module_id, timeq_callback_t *callback, void *data) { + struct timeq_entry *entry = timeq_uadd(useconds, module_id, callback, data); entry->name = strdup(name); return entry; } int timeq_del(struct timeq_entry* entry) { - struct timeq_entry *centry, *last = NULL; - for(centry = timeq_events; centry; centry = centry->next) { - if(centry == entry) { - if(last) - last->next = centry->next; - else - timeq_events = centry->next; - if(centry->name) - free(centry->name); - free(centry); - return 1; - } else { - last = centry; - } - } - return 0; + #ifdef HAVE_THREADS + if(!pthread_mutex_initialized) return 0; + #endif + SYNCHRONIZE(synchronized); + if(entry->next) + entry->next->prev = entry->prev; + if(entry->prev) + entry->prev->next = entry->next; + else + timeq_events = entry->next; + if(entry->name) + free(entry->name); + if(entry->iofd) + iohandler_close(entry->iofd); + free(entry); + DESYNCHRONIZE(synchronized); + return 1; } int timeq_del_name(char *name) { - struct timeq_entry *centry, *last = NULL; - for(centry = timeq_events; centry; centry = centry->next) { - if(centry->name && !stricmp(centry->name, name)) { - if(last) - last->next = centry->next; - else - timeq_events = centry->next; - free(centry->name); - free(centry); - return 1; - } else { - last = centry; + SYNCHRONIZE(synchronized); + struct timeq_entry *entry; + int removed = 0; + for(entry = timeq_events; entry; entry = entry->next) { + if(entry->name && !stricmp(entry->name, name)) { + removed = timeq_del(entry); + break; } } - return 0; + DESYNCHRONIZE(synchronized); + return removed; } int timeq_name_exists(char *name) { + SYNCHRONIZE(synchronized); struct timeq_entry *centry; for(centry = timeq_events; centry; centry = centry->next) { if(centry->name && !stricmp(centry->name, name)) { + DESYNCHRONIZE(synchronized); return 1; } } + DESYNCHRONIZE(synchronized); return 0; } + +void unregister_module_timers(int module_id) { + SYNCHRONIZE(synchronized); + struct timeq_entry *entry, *next_entry; + for(entry = timeq_events; entry; entry = next_entry) { + next_entry = entry->next; + if(entry->module_id == module_id) + timeq_del(entry); + } + DESYNCHRONIZE(synchronized); +}