From 7e7834af2c8383c19742f0e2a5bfea6a30d7a9ab Mon Sep 17 00:00:00 2001 From: ac-stef Date: Fri, 22 Aug 2014 14:14:29 +0200 Subject: [PATCH] wrapper functions for threading and semaphores allow the standalone linux server to use posix libraries instead of SDL (using SDL can be forced by defining AC_FORCE_SDL_THREADS) --- source/src/Makefile | 2 +- source/src/platform.h | 4 ++ source/src/tools.cpp | 141 ++++++++++++++++++++++++++++++++++++++++++ source/src/tools.h | 16 +++++ 4 files changed, 162 insertions(+), 1 deletion(-) diff --git a/source/src/Makefile b/source/src/Makefile index 679db095..2ae8ca0f 100644 --- a/source/src/Makefile +++ b/source/src/Makefile @@ -101,7 +101,7 @@ SERVER_INCLUDES= -DSTANDALONE $(INCLUDES) -I../include SERVER_LIBS= -L../lib -lzdll -lenet -llibintl -lws2_32 -lwinmm else SERVER_INCLUDES= -DSTANDALONE $(INCLUDES) -SERVER_LIBS= -L../enet/.libs -lenet -lz +SERVER_LIBS= -L../enet/.libs -lenet -lz -lpthread endif SERVER_OBJS= \ diff --git a/source/src/platform.h b/source/src/platform.h index aece7e24..25177f79 100644 --- a/source/src/platform.h +++ b/source/src/platform.h @@ -72,6 +72,10 @@ #include #endif +#if defined(WIN32) || defined(__APPLE__) || !defined(STANDALONE) || defined(AC_FORCE_SDL_THREADS) + #define AC_USE_SDL_THREADS +#endif + #ifndef CURL_STATICLIB #define CURL_STATICLIB #endif diff --git a/source/src/tools.cpp b/source/src/tools.cpp index 0dad0018..f7be9af9 100644 --- a/source/src/tools.cpp +++ b/source/src/tools.cpp @@ -486,3 +486,144 @@ bool glmatrixf::invert(const glmatrixf &m, float mindet) return true; } +// multithreading and ipc tools wrapper for the server +// all embedded servers and all standalone servers except on linux use SDL +// the standalone linux version uses native linux libraries - and also makes use of shared memory + +#ifdef AC_USE_SDL_THREADS + #include "SDL_thread.h" // also fetches SDL_mutex.h +#else + #include + #include + #include +#endif + +static int sl_sem_errorcountdummy = 0; + +#ifdef AC_USE_SDL_THREADS +sl_semaphore::sl_semaphore(int init, int *ecnt) +{ + data = (void *)SDL_CreateSemaphore(init); + errorcount = ecnt ? ecnt : &sl_sem_errorcountdummy; + if(data == NULL) (*errorcount)++; +} + +sl_semaphore::~sl_semaphore() +{ + if(data) SDL_DestroySemaphore((SDL_sem *) data); +} + +void sl_semaphore::wait() +{ + if(SDL_SemWait((SDL_sem *) data) != 0) (*errorcount)++; +} + +int sl_semaphore::trywait() +{ + return SDL_SemTryWait((SDL_sem *) data); +} + +int sl_semaphore::getvalue() +{ + return SDL_SemValue((SDL_sem *) data); +} + +void sl_semaphore::post() +{ + if(SDL_SemPost((SDL_sem *) data) != 0) (*errorcount)++; +} +#else +sl_semaphore::sl_semaphore(int init, int *ecnt) +{ + errorcount = ecnt ? ecnt : &sl_sem_errorcountdummy; + data = (void *) new sem_t; + if(data == NULL || sem_init((sem_t *) data, 0, init) != 0) (*errorcount)++; +} + +sl_semaphore::~sl_semaphore() +{ + if(data) + { + if(sem_destroy((sem_t *) data) != 0) (*errorcount)++; + delete (sem_t *)data; + } +} + +void sl_semaphore::wait() +{ + if(sem_wait((sem_t *) data) != 0) (*errorcount)++; +} + +int sl_semaphore::trywait() +{ + return sem_trywait((sem_t *) data); +} + +int sl_semaphore::getvalue() +{ + int ret; + if(sem_getvalue((sem_t *) data, &ret) != 0) (*errorcount)++; + return ret; +} + +void sl_semaphore::post() +{ + if(sem_post((sem_t *) data) != 0) (*errorcount)++; +} +#endif + +// (wrapping threads is slightly ugly, since SDL threads use a different return value (int) than pthreads (void *) - and that can't be solved with a typecast) +#ifdef AC_USE_SDL_THREADS +struct sl_threadinfo { int (*fn)(void *); void *data; SDL_Thread *handle; }; + +static int sl_thread_indir(void *info) { return (*((sl_threadinfo*)info)->fn)(((sl_threadinfo*)info)->data); } + +void *sl_createthread(int (*fn)(void *), void *data) +{ + sl_threadinfo *ti = new sl_threadinfo; + ti->data = data; + ti->fn = fn; + ti->handle = SDL_CreateThread(sl_thread_indir, ti); + return (void *) ti; +} + +int sl_waitthread(void *ti) +{ + int res; + SDL_WaitThread(((sl_threadinfo *)ti)->handle, &res); + delete (sl_threadinfo *) ti; + return res; +} +#else +struct sl_threadinfo { int (*fn)(void *); void *data; pthread_t handle; int res; }; + +static void *sl_thread_indir(void *info) +{ + sl_threadinfo *ti = (sl_threadinfo*) info; + ti->res = (ti->fn)(ti->data); + return &ti->res; +} + +void *sl_createthread(int (*fn)(void *), void *data) +{ + sl_threadinfo *ti = new sl_threadinfo; + ti->data = data; + ti->fn = fn; + pthread_create(&(ti->handle), NULL, sl_thread_indir, ti); + return (void *) ti; +} + +int sl_waitthread(void *ti) +{ + void *res; + pthread_join(((sl_threadinfo *)ti)->handle, &res); + int ires = *((int *)res); + delete (sl_threadinfo *) ti; + return ires; +} +#endif + + + + + diff --git a/source/src/tools.h b/source/src/tools.h index 90480d45..591ba816 100644 --- a/source/src/tools.h +++ b/source/src/tools.h @@ -979,5 +979,21 @@ extern const char *hiddenpwd(const char *pwd, int showchars = 0); extern void stackdumper(unsigned int type, EXCEPTION_POINTERS *ep); #endif +struct sl_semaphore +{ + void *data; + int *errorcount; + + sl_semaphore(int init, int *errorcount); // init: initial semaphore value; errorcount: pointer to error counter for semaphore-related errors or NULL + ~sl_semaphore(); + void wait(); // blocks, until semaphore gets available + int trywait(); // returns 0, if semaphore was locked (like wait(), but returns !=0 instead of blocking) + int getvalue(); // returns current semaphore value + void post(); // increments (unlocks) semaphore +}; + +extern void *sl_createthread(int (*fn)(void *), void *data); +extern int sl_waitthread(void *ti); + #endif