[IOMultiplexerV2] alpha
[NextIRCd.git] / src / IOHandler / IOGarbageCollector.c
diff --git a/src/IOHandler/IOGarbageCollector.c b/src/IOHandler/IOGarbageCollector.c
new file mode 100644 (file)
index 0000000..d624396
--- /dev/null
@@ -0,0 +1,102 @@
+/* IOGarbageCollector.c - IOMultiplexer v2
+ * Copyright (C) 2014  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
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License 
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. 
+ */
+#define _IOHandler_internals
+#include "IOInternal.h"
+#include "IOHandler.h"
+#include "IOGarbageCollector.h"
+#include "IOLog.h"
+
+#include <sys/time.h>
+#include <stdlib.h>
+
+struct IOGCObject {
+       void *object;
+       iogc_free *free_callback;
+       struct timeval timeout;
+       
+       struct IOGCObject *next;
+};
+
+static int iogc_enabled = 1;
+static struct timeval iogc_timeout;
+static struct IOGCObject *first_object = NULL, *last_object = NULL;
+
+void iogc_init() {
+       iogc_timeout.tv_usec = 0;
+       iogc_timeout.tv_sec = 10;
+}
+
+
+void iohandler_set_gc(int enabled) {
+       if(enabled)
+               iogc_enabled = 1;
+       else
+               iogc_enabled = 0;
+}
+
+void iogc_add(void *object) {
+       iogc_add_callback(object, NULL);
+}
+
+void iogc_add_callback(void *object, iogc_free *free_callback) {
+       if(!iogc_enabled) {
+               if(free_callback)
+                       free_callback(object);
+               else
+                       free(object);
+               return;
+       }
+       struct IOGCObject *obj = malloc(sizeof(*obj));
+    if(!obj) {
+        iolog_trigger(IOLOG_ERROR, "could not allocate memory for IOGCObject in %s:%d", __FILE__, __LINE__);
+               if(free_callback)
+                       free_callback(object);
+               else
+                       free(object);
+        return;
+    }
+       obj->object = object;
+       obj->free_callback = free_callback;
+       gettimeofday(&obj->timeout, NULL);
+       obj->timeout.tv_sec += IOGC_TIMEOUT;
+       
+       obj->next = NULL;
+       if(last_object)
+               last_object->next = obj;
+       else
+               first_object = obj;
+       last_object = obj;
+}
+
+void iogc_exec() {
+       struct timeval now;
+       gettimeofday(&now, NULL);
+       
+       struct IOGCObject *obj, *next_obj;
+       for(obj = first_object; obj; obj = next_obj) {
+               if(timeval_is_smaler(obj->timeout, now)) {
+                       next_obj = obj->next;
+                       if(obj->free_callback)
+                               obj->free_callback(obj->object);
+                       else
+                               free(obj->object);
+                       free(obj);
+               } else
+                       break;
+       }
+       first_object = obj;
+}