-/* timeq.c - NeonServ v5.1
- * Copyright (C) 2011 Philipp Kreil (pk910)
+/* timeq.c - NeonServ v5.5
+ * Copyright (C) 2011-2012 Philipp Kreil (pk910)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
*/
#include "timeq.h"
+#include "IOHandler.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;
- free(entry);
- } else
- break;
+static IOHANDLER_CALLBACK(timeq_callback) {
+ struct timeq_entry *entry = event->iofd->data;
+ switch(event->type) {
+ case IOEVENT_TIMEOUT:
+ entry->callback(entry->data);
+ entry->iofd = NULL;
+ timeq_del(entry);
+ break;
+ default:
+ break;
}
- timeq_events = entry;
}
-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");
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);
+}