From 6d138194b425c64e2177b4493fe8d2cf2ecac7ae Mon Sep 17 00:00:00 2001 From: Robin Watts Date: Mon, 21 Nov 2016 12:20:09 +0000 Subject: Move threading macros out into a mu-threads helper file. --- source/helpers/mu-threads/mu-threads.c | 283 +++++++++++++++++++++++++++++++++ 1 file changed, 283 insertions(+) create mode 100644 source/helpers/mu-threads/mu-threads.c (limited to 'source/helpers') diff --git a/source/helpers/mu-threads/mu-threads.c b/source/helpers/mu-threads/mu-threads.c new file mode 100644 index 00000000..bbc87d1a --- /dev/null +++ b/source/helpers/mu-threads/mu-threads.c @@ -0,0 +1,283 @@ +#include "mupdf/helpers/mu-threads.h" + +#ifdef DISABLE_MUTHREADS + +#include + +/* Null implementation. Just error out. */ + +int mu_create_semaphore(mu_semaphore *sem) +{ + return 1; /* Just Error */ +} + +void mu_destroy_semaphore(mu_semaphore *sem) +{ +} + +int mu_trigger_semaphore(mu_semaphore *sem) +{ + abort(); + return 1; +} + +int mu_wait_semaphore(mu_semaphore *sem) +{ + abort(); + return 1; +} + +int mu_create_thread(mu_thread *th, mu_thread_fn *fn, void *arg) +{ + return 1; +} + +void mu_destroy_thread(mu_thread *th) +{ +} + +int mu_create_mutex(mu_mutex *mutex) +{ + return 1; +} + +void mu_destroy_mutex(mu_mutex *mutex) +{ +} + +void mu_lock_mutex(mu_mutex *mutex) +{ + abort(); +} + +void mu_unlock_mutex(mu_mutex *mutex) +{ + abort(); +} + +#elif MU_THREAD_IMPL_TYPE == 1 + +/* Windows threads */ +int mu_create_semaphore(mu_semaphore *sem) +{ + sem->handle = CreateSemaphore(NULL, 0, 1, NULL); + return (sem->handle != NULL); +} + +void mu_destroy_semaphore(mu_semaphore *sem) +{ + if (sem->handle == NULL) + return; + /* We can't sensibly handle this failing */ + (void)CloseHandle(sem->handle); +} + +int mu_trigger_semaphore(mu_semaphore *sem) +{ + if (sem->handle == NULL) + return 0; + /* We can't sensibly handle this failing */ + return !ReleaseSemaphore(sem->handle, 1, NULL); +} + +int mu_wait_semaphore(mu_semaphore *sem) +{ + if (sem->handle == NULL) + return 0; + /* We can't sensibly handle this failing */ + return !WaitForSingleObject(sem->handle, INFINITE); +} + +static DWORD WINAPI thread_starter(LPVOID arg) +{ + mu_thread *th = (mu_thread *)arg; + + th->fn(th->arg); + + return 0; +} + +int mu_create_thread(mu_thread *th, mu_thread_fn *fn, void *arg) +{ + th->fn = fn; + th->arg = arg; + th->handle = CreateThread(NULL, 0, thread_starter, th, 0, NULL); + + return (th->handle != NULL); +} + +void mu_destroy_thread(mu_thread *th) +{ + if (th->handle == NULL) + return; + /* We can't sensibly handle this failing */ + (void)WaitForSingleObject(th->handle, INFINITE); + (void)CloseHandle(th->handle); +} + +int mu_create_mutex(mu_mutex *mutex) +{ + InitializeCriticalSection(&mutex->mutex); + return 0; /* Magic function, never fails */ +} + +void mu_destroy_mutex(mu_mutex *mutex) +{ + const static CRITICAL_SECTION empty = { 0 }; + if (memcmp(&mutex->mutex, &empty, sizeof(empty)) == 0) + return; + DeleteCriticalSection(&mutex->mutex); + mutex->mutex = empty; +} + +void mu_lock_mutex(mu_mutex *mutex) +{ + EnterCriticalSection(&mutex->mutex); +} + +void mu_unlock_mutex(mu_mutex *mutex) +{ + LeaveCriticalSection(&mutex->mutex); +} + +#elif MU_THREAD_IMPL_TYPE == 2 + +/* + PThreads - without working unnamed semaphores. + + Neither ios nor OSX supports unnamed semaphores. + Named semaphores are a pain to use, so we implement + our own sempahores using condition variables and + mutexes. +*/ + +#include + +struct mu_sempahore +{ + int count; + pthread_mutex_t mutex; + pthread_cond_t cond; +}; + +int +mu_create_semaphore(mu_semaphore *sem) +{ + int scode; + + sem->count = 0; + scode = pthread_mutex_init(&sem->mutex, NULL); + if (scode == 0) + { + scode = pthread_cond_init(&sem->cond, NULL); + if (scode) + pthread_mutex_destroy(&sem->mutex); + } + if (scode) + memset(sem, 0, sizeof(*sem)); + return scode; +} + +void +mu_destroy_semaphore(mu_semaphore *sem) +{ + const static mu_semaphore empty = { 0 }; + + if (memcmp(sem, &empty, sizeof(empty)) == 0) + return; + (void)pthread_cond_destroy(&sem->cond); + (void)pthread_mutex_destroy(&sem->mutex); + *sem = empty; +} + +int +mu_wait_semaphore(mu_semaphore *sem) +{ + int scode, scode2; + + scode = pthread_mutex_lock(&sem->mutex); + if (scode) + return scode; + while (sem->count == 0) { + scode = pthread_cond_wait(&sem->cond, &sem->mutex); + if (scode) + break; + } + if (scode == 0) + --sem->count; + scode2 = pthread_mutex_unlock(&sem->mutex); + if (scode == 0) + scode = scode2; + return scode; +} + +int +mu_trigger_semaphore(mu_semaphore * sem) +{ + int scode, scode2; + + scode = pthread_mutex_lock(&sem->mutex); + if (scode) + return scode; + if (sem->count++ == 0) + scode = pthread_cond_signal(&sem->cond); + scode2 = pthread_mutex_unlock(&sem->mutex); + if (scode == 0) + scode = scode2; + return scode; +} + +static void *thread_starter(void *arg) +{ + mu_thread *th = (mu_thread *)arg; + + th->fn(th->arg); + + return NULL; +} + +int mu_create_thread(mu_thread *th, mu_thread_fn *fn, void *arg) +{ + th->fn = fn; + th->arg = arg; + return pthread_create(&th->thread, NULL, thread_starter, th); +} + +void mu_destroy_thread(mu_thread *th) +{ + const static mu_thread empty = { 0 }; + + if (memcmp(th, &empty, sizeof(empty)) == 0) + return; + + (void)pthread_join(th->thread, NULL); + *th = empty; +} + +int mu_create_mutex(mu_mutex *mutex) +{ + return pthread_mutex_init(&mutex->mutex, NULL); +} + +void mu_destroy_mutex(mu_mutex *mutex) +{ + const static mu_mutex empty = { 0 }; + if (memcmp(mutex, &empty, sizeof(empty)) == 0) + return; + (void)pthread_mutex_destroy(&mutex->mutex); + *mutex = empty; +} + +void mu_lock_mutex(mu_mutex *mutex) +{ + (void)pthread_mutex_lock(&mutex->mutex); +} + +void mu_unlock_mutex(mu_mutex *mutex) +{ + (void)pthread_mutex_unlock(&mutex->mutex); +} + +#else +#error Unknown MU_THREAD_IMPL_TYPE setting +#endif -- cgit v1.2.3