summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/thread.c140
-rw-r--r--src/thread.h76
-rw-r--r--src/utils.c92
-rw-r--r--src/utils.h52
4 files changed, 360 insertions, 0 deletions
diff --git a/src/thread.c b/src/thread.c
new file mode 100644
index 0000000..eb535ab
--- /dev/null
+++ b/src/thread.c
@@ -0,0 +1,140 @@
+/*
+ * thread.c
+ *
+ * Copyright (c) 2012-2019 Nikias Bassen, All Rights Reserved.
+ * Copyright (c) 2012 Martin Szulecki, All Rights Reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "thread.h"
+
+int thread_new(THREAD_T *thread, thread_func_t thread_func, void* data)
+{
+#ifdef WIN32
+ HANDLE th = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)thread_func, data, 0, NULL);
+ if (th == NULL) {
+ return -1;
+ }
+ *thread = th;
+ return 0;
+#else
+ int res = pthread_create(thread, NULL, thread_func, data);
+ return res;
+#endif
+}
+
+void thread_detach(THREAD_T thread)
+{
+#ifdef WIN32
+ CloseHandle(thread);
+#else
+ pthread_detach(thread);
+#endif
+}
+
+void thread_free(THREAD_T thread)
+{
+#ifdef WIN32
+ CloseHandle(thread);
+#endif
+}
+
+int thread_join(THREAD_T thread)
+{
+ /* wait for thread to complete */
+#ifdef WIN32
+ return (int)WaitForSingleObject(thread, INFINITE);
+#else
+ return pthread_join(thread, NULL);
+#endif
+}
+
+int thread_alive(THREAD_T thread)
+{
+#ifdef WIN32
+ return WaitForSingleObject(thread, 0) == WAIT_TIMEOUT;
+#else
+ return pthread_kill(thread, 0) == 0;
+#endif
+}
+
+int thread_cancel(THREAD_T thread)
+{
+#ifdef WIN32
+ return -1;
+#else
+#ifdef HAVE_PTHREAD_CANCEL
+ return pthread_cancel(thread);
+#else
+ return -1;
+#endif
+#endif
+}
+
+void mutex_init(mutex_t* mutex)
+{
+#ifdef WIN32
+ InitializeCriticalSection(mutex);
+#else
+ pthread_mutex_init(mutex, NULL);
+#endif
+}
+
+void mutex_destroy(mutex_t* mutex)
+{
+#ifdef WIN32
+ DeleteCriticalSection(mutex);
+#else
+ pthread_mutex_destroy(mutex);
+#endif
+}
+
+void mutex_lock(mutex_t* mutex)
+{
+#ifdef WIN32
+ EnterCriticalSection(mutex);
+#else
+ pthread_mutex_lock(mutex);
+#endif
+}
+
+void mutex_unlock(mutex_t* mutex)
+{
+#ifdef WIN32
+ LeaveCriticalSection(mutex);
+#else
+ pthread_mutex_unlock(mutex);
+#endif
+}
+
+void thread_once(thread_once_t *once_control, void (*init_routine)(void))
+{
+#ifdef WIN32
+ while (InterlockedExchange(&(once_control->lock), 1) != 0) {
+ Sleep(1);
+ }
+ if (!once_control->state) {
+ once_control->state = 1;
+ init_routine();
+ }
+ InterlockedExchange(&(once_control->lock), 0);
+#else
+ pthread_once(once_control, init_routine);
+#endif
+}
diff --git a/src/thread.h b/src/thread.h
new file mode 100644
index 0000000..23e4510
--- /dev/null
+++ b/src/thread.h
@@ -0,0 +1,76 @@
+/*
+ * thread.h
+ *
+ * Copyright (c) 2012-2019 Nikias Bassen, All Rights Reserved.
+ * Copyright (c) 2012 Martin Szulecki, All Rights Reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __THREAD_H
+#define __THREAD_H
+
+#include <stddef.h>
+
+#ifdef WIN32
+#include <windows.h>
+typedef HANDLE THREAD_T;
+typedef CRITICAL_SECTION mutex_t;
+typedef volatile struct {
+ LONG lock;
+ int state;
+} thread_once_t;
+#define THREAD_ONCE_INIT {0, 0}
+#define THREAD_ID GetCurrentThreadId()
+#define THREAD_T_NULL (THREAD_T)NULL
+#else
+#include <pthread.h>
+#include <signal.h>
+typedef pthread_t THREAD_T;
+typedef pthread_mutex_t mutex_t;
+typedef pthread_once_t thread_once_t;
+#define THREAD_ONCE_INIT PTHREAD_ONCE_INIT
+#define THREAD_ID pthread_self()
+#define THREAD_T_NULL (THREAD_T)NULL
+#endif
+
+typedef void* (*thread_func_t)(void* data);
+
+int thread_new(THREAD_T* thread, thread_func_t thread_func, void* data);
+void thread_detach(THREAD_T thread);
+void thread_free(THREAD_T thread);
+int thread_join(THREAD_T thread);
+int thread_alive(THREAD_T thread);
+
+int thread_cancel(THREAD_T thread);
+
+#ifdef WIN32
+#undef HAVE_THREAD_CLEANUP
+#else
+#ifdef HAVE_PTHREAD_CANCEL
+#define HAVE_THREAD_CLEANUP 1
+#define thread_cleanup_push(routine, arg) pthread_cleanup_push(routine, arg)
+#define thread_cleanup_pop(execute) pthread_cleanup_pop(execute)
+#endif
+#endif
+
+void mutex_init(mutex_t* mutex);
+void mutex_destroy(mutex_t* mutex);
+void mutex_lock(mutex_t* mutex);
+void mutex_unlock(mutex_t* mutex);
+
+void thread_once(thread_once_t *once_control, void (*init_routine)(void));
+
+#endif
diff --git a/src/utils.c b/src/utils.c
new file mode 100644
index 0000000..826bfbe
--- /dev/null
+++ b/src/utils.c
@@ -0,0 +1,92 @@
+/*
+ * utils.c
+ *
+ * Copyright (C) 2009 Hector Martin <hector@marcansoft.com>
+ * Copyright (C) 2009 Nikias Bassen <nikias@gmx.li>
+ * Copyright (c) 2013 Federico Mena Quintero
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 2.1 of the
+ * License, or (at your option) any later version.
+ *
+ * This library 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 Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include "utils.h"
+
+#define CAPACITY_STEP 8
+
+void collection_init(struct collection *col)
+{
+ col->list = malloc(sizeof(void *) * CAPACITY_STEP);
+ memset(col->list, 0, sizeof(void *) * CAPACITY_STEP);
+ col->capacity = CAPACITY_STEP;
+}
+
+void collection_free(struct collection *col)
+{
+ free(col->list);
+ col->list = NULL;
+ col->capacity = 0;
+}
+
+void collection_add(struct collection *col, void *element)
+{
+ int i;
+ for(i=0; i<col->capacity; i++) {
+ if(!col->list[i]) {
+ col->list[i] = element;
+ return;
+ }
+ }
+ col->list = realloc(col->list, sizeof(void*) * (col->capacity + CAPACITY_STEP));
+ memset(&col->list[col->capacity], 0, sizeof(void *) * CAPACITY_STEP);
+ col->list[col->capacity] = element;
+ col->capacity += CAPACITY_STEP;
+}
+
+void collection_remove(struct collection *col, void *element)
+{
+ int i;
+ for(i=0; i<col->capacity; i++) {
+ if(col->list[i] == element) {
+ col->list[i] = NULL;
+ return;
+ }
+ }
+}
+
+int collection_count(struct collection *col)
+{
+ int i, cnt = 0;
+ for(i=0; i<col->capacity; i++) {
+ if(col->list[i])
+ cnt++;
+ }
+ return cnt;
+}
+
+void collection_copy(struct collection *dest, struct collection *src)
+{
+ if (!dest || !src) return;
+ dest->capacity = src->capacity;
+ dest->list = malloc(sizeof(void*) * src->capacity);
+ memcpy(dest->list, src->list, sizeof(void*) * src->capacity);
+}
diff --git a/src/utils.h b/src/utils.h
new file mode 100644
index 0000000..ccb3a09
--- /dev/null
+++ b/src/utils.h
@@ -0,0 +1,52 @@
+/*
+ * utils.h
+ *
+ * Copyright (C) 2009 Hector Martin <hector@marcansoft.com>
+ * Copyright (C) 2009 Nikias Bassen <nikias@gmx.li>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 2.1 of the
+ * License, or (at your option) any later version.
+ *
+ * This library 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 Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef UTILS_H
+#define UTILS_H
+
+struct collection {
+ void **list;
+ int capacity;
+};
+
+void collection_init(struct collection *col);
+void collection_add(struct collection *col, void *element);
+void collection_remove(struct collection *col, void *element);
+int collection_count(struct collection *col);
+void collection_free(struct collection *col);
+void collection_copy(struct collection *dest, struct collection *src);
+
+#define MERGE_(a,b) a ## _ ## b
+#define LABEL_(a,b) MERGE_(a, b)
+#define UNIQUE_VAR(a) LABEL_(a, __LINE__)
+
+#define FOREACH(var, col) \
+ do { \
+ int UNIQUE_VAR(_iter); \
+ for(UNIQUE_VAR(_iter)=0; UNIQUE_VAR(_iter)<(col)->capacity; UNIQUE_VAR(_iter)++) { \
+ if(!(col)->list[UNIQUE_VAR(_iter)]) continue; \
+ var = (col)->list[UNIQUE_VAR(_iter)];
+
+#define ENDFOREACH \
+ } \
+ } while(0);
+
+#endif