-/* timeq.c - NeonServ v5.2
- * Copyright (C) 2011 Philipp Kreil (pk910)
+/* timeq.c - NeonServ v5.3
+ * 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"
static struct timeq_entry *timeq_events;
+#ifdef HAVE_THREADS
+static pthread_mutex_t synchronized;
+#endif
+
+void init_timeq() {
+ THREAD_MUTEX_INIT(synchronized);
+}
void timeq_tick() {
+ SYNCHRONIZE(synchronized);
struct timeq_entry *entry, *next;
- time_t now = time(0);
+ struct timeval now;
+ gettimeofday(&now, NULL);
for(entry = timeq_events; entry; entry = next) {
- if(entry->execute <= now) {
- entry->callback(entry->data);
+ if(!timeval_is_bigger(entry->execute, now)) {
next = entry->next;
if(timeq_events == entry)
timeq_events = next;
+ entry->callback(entry->data);
free(entry);
} else
break;
}
+ DESYNCHRONIZE(synchronized);
+}
+
+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_add(int seconds, timeq_callback_t *callback, void *data) {
- time_t now = time(0);
+struct timeq_entry* timeq_uadd(int useconds, int module_id, timeq_callback_t *callback, void *data) {
+ struct timeval now;
+ gettimeofday(&now, NULL);
struct timeq_entry *entry = malloc(sizeof(*entry));
if (!entry)
{
perror("malloc() failed");
return NULL;
}
- entry->execute = now + seconds;
+ SYNCHRONIZE(synchronized);
+ now.tv_usec += (useconds % 1000);
+ now.tv_sec += (useconds / 1000);
+ entry->execute = now;
+ 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)
+ if(timeval_is_bigger(next->execute, now))
break;
else
prev = next;
entry->next = next;
prev->next = 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) {
+ SYNCHRONIZE(synchronized);
+ struct timeq_entry *entry = timeq_uadd(useconds, module_id, callback, data);
entry->name = strdup(name);
+ DESYNCHRONIZE(synchronized);
return entry;
}
int timeq_del(struct timeq_entry* entry) {
+ SYNCHRONIZE(synchronized);
struct timeq_entry *centry, *last = NULL;
for(centry = timeq_events; centry; centry = centry->next) {
if(centry == entry) {
if(centry->name)
free(centry->name);
free(centry);
+ DESYNCHRONIZE(synchronized);
return 1;
} else {
last = centry;
}
}
+ DESYNCHRONIZE(synchronized);
return 0;
}
int timeq_del_name(char *name) {
+ SYNCHRONIZE(synchronized);
struct timeq_entry *centry, *last = NULL;
for(centry = timeq_events; centry; centry = centry->next) {
if(centry->name && !stricmp(centry->name, name)) {
timeq_events = centry->next;
free(centry->name);
free(centry);
+ DESYNCHRONIZE(synchronized);
return 1;
} else {
last = centry;
}
}
+ DESYNCHRONIZE(synchronized);
return 0;
}
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 *centry, *next, *last = NULL;
+ for(centry = timeq_events; centry; centry = next) {
+ next = centry->next;
+ if(centry->module_id == module_id) {
+ if(last)
+ last->next = centry->next;
+ else
+ timeq_events = centry->next;
+ free(centry->name);
+ free(centry);
+ } else
+ last = centry;
+ }
+ DESYNCHRONIZE(synchronized);
+}