diff --git a/Makefile b/Makefile index 32db22e..d2f5c8f 100644 --- a/Makefile +++ b/Makefile @@ -185,7 +185,6 @@ IS_X86 = 1 endif ifeq ($(NEED_THREADING), 1) -THREAD_STUBS += thread.cpp stubs_thread.cpp FLAGS += -DWANT_THREADING endif diff --git a/stubs.cpp b/stubs.cpp index f699552..1f4e03f 100644 --- a/stubs.cpp +++ b/stubs.cpp @@ -137,3 +137,329 @@ uint32 MDFND_GetTime() return ms - start_ms; } +#ifdef WANT_THREADING + +#include "thread.h" +#include + +#if defined(_WIN32) && !defined(_XBOX) +#define WIN32_LEAN_AND_MEAN +#include +#elif defined(_XBOX) +#include +#elif defined(GEKKO) +#include "thread/gx_pthread.h" +#else +#include +#include +#endif + +#ifdef __MACH__ +#include +#include +#endif + +struct thread_data +{ + void (*func)(void*); + void *userdata; +}; + +#ifdef _WIN32 + +struct sthread +{ + HANDLE thread; +}; + +static DWORD CALLBACK thread_wrap(void *data_) +{ + struct thread_data *data = (struct thread_data*)data_; + data->func(data->userdata); + free(data); + return 0; +} + +sthread_t *sthread_create(void (*thread_func)(void*), void *userdata) +{ + sthread_t *thread = (sthread_t*)calloc(1, sizeof(*thread)); + if (!thread) + return NULL; + + struct thread_data *data = (struct thread_data*)calloc(1, sizeof(*data)); + if (!data) + { + free(thread); + return NULL; + } + + data->func = thread_func; + data->userdata = userdata; + + thread->thread = CreateThread(NULL, 0, thread_wrap, data, 0, NULL); + if (!thread->thread) + { + free(data); + free(thread); + return NULL; + } + + return thread; +} + +void sthread_join(sthread_t *thread) +{ + WaitForSingleObject(thread->thread, INFINITE); + CloseHandle(thread->thread); + free(thread); +} + +struct slock +{ + CRITICAL_SECTION lock; +}; + +slock_t *slock_new(void) +{ + slock_t *lock = (slock_t*)calloc(1, sizeof(*lock)); + if (!lock) + return NULL; + + InitializeCriticalSection(&lock->lock); + return lock; +} + +void slock_free(slock_t *lock) +{ + DeleteCriticalSection(&lock->lock); + free(lock); +} + +void slock_lock(slock_t *lock) +{ + EnterCriticalSection(&lock->lock); +} + +void slock_unlock(slock_t *lock) +{ + LeaveCriticalSection(&lock->lock); +} + +struct scond +{ + HANDLE event; +}; + +scond_t *scond_new(void) +{ + scond_t *cond = (scond_t*)calloc(1, sizeof(*cond)); + if (!cond) + return NULL; + + cond->event = CreateEvent(NULL, FALSE, FALSE, NULL); + if (!cond->event) + { + free(cond); + return NULL; + } + + return cond; +} + +void scond_wait(scond_t *cond, slock_t *lock) +{ + WaitForSingleObject(cond->event, 0); + slock_unlock(lock); + + WaitForSingleObject(cond->event, INFINITE); + + slock_lock(lock); +} + +int scond_wait_timeout(scond_t *cond, slock_t *lock, unsigned timeout_ms) +{ + WaitForSingleObject(cond->event, 0); + slock_unlock(lock); + + DWORD res = WaitForSingleObject(cond->event, timeout_ms); + + slock_lock(lock); + return res == WAIT_OBJECT_0; +} + +void scond_signal(scond_t *cond) +{ + SetEvent(cond->event); +} + +void scond_free(scond_t *cond) +{ + CloseHandle(cond->event); + free(cond); +} + +#else + +struct sthread +{ + pthread_t id; +}; + +static void *thread_wrap(void *data_) +{ + struct thread_data *data = (struct thread_data*)data_; + data->func(data->userdata); + free(data); + return NULL; +} + +sthread_t *sthread_create(void (*thread_func)(void*), void *userdata) +{ + sthread_t *thr = (sthread_t*)calloc(1, sizeof(*thr)); + if (!thr) + return NULL; + + struct thread_data *data = (struct thread_data*)calloc(1, sizeof(*data)); + if (!data) + { + free(thr); + return NULL; + } + + data->func = thread_func; + data->userdata = userdata; + + if (pthread_create(&thr->id, NULL, thread_wrap, data) < 0) + { + free(data); + free(thr); + return NULL; + } + + return thr; +} + +void sthread_join(sthread_t *thread) +{ + pthread_join(thread->id, NULL); + free(thread); +} + +struct slock +{ + pthread_mutex_t lock; +}; + +slock_t *slock_new(void) +{ + slock_t *lock = (slock_t*)calloc(1, sizeof(*lock)); + if (!lock) + return NULL; + + if (pthread_mutex_init(&lock->lock, NULL) < 0) + { + free(lock); + return NULL; + } + + return lock; +} + +void slock_free(slock_t *lock) +{ + pthread_mutex_destroy(&lock->lock); + free(lock); +} + +void slock_lock(slock_t *lock) +{ + pthread_mutex_lock(&lock->lock); +} + +void slock_unlock(slock_t *lock) +{ + pthread_mutex_unlock(&lock->lock); +} + +struct scond +{ + pthread_cond_t cond; +}; + +scond_t *scond_new(void) +{ + scond_t *cond = (scond_t*)calloc(1, sizeof(*cond)); + if (!cond) + return NULL; + + if (pthread_cond_init(&cond->cond, NULL) < 0) + { + free(cond); + return NULL; + } + + return cond; +} + +void scond_free(scond_t *cond) +{ + pthread_cond_destroy(&cond->cond); + free(cond); +} + +void scond_wait(scond_t *cond, slock_t *lock) +{ + pthread_cond_wait(&cond->cond, &lock->lock); +} + +void scond_signal(scond_t *cond) +{ + pthread_cond_signal(&cond->cond); +} + +#endif + +MDFN_Thread *MDFND_CreateThread(int (*fn)(void *), void *data) +{ + return (MDFN_Thread*)sthread_create((void (*)(void*))fn, data); +} + +void MDFND_WaitThread(MDFN_Thread *thr, int *val) +{ + sthread_join((sthread_t*)thr); + + if (val) + { + *val = 0; + fprintf(stderr, "WaitThread relies on return value.\n"); + } +} + +void MDFND_KillThread(MDFN_Thread *) +{ + fprintf(stderr, "Killing a thread is a BAD IDEA!\n"); +} + +MDFN_Mutex *MDFND_CreateMutex() +{ + return (MDFN_Mutex*)slock_new(); +} + +void MDFND_DestroyMutex(MDFN_Mutex *lock) +{ + slock_free((slock_t*)lock); +} + +int MDFND_LockMutex(MDFN_Mutex *lock) +{ + slock_lock((slock_t*)lock); + return 0; +} + +int MDFND_UnlockMutex(MDFN_Mutex *lock) +{ + slock_unlock((slock_t*)lock); + return 0; +} + +#endif diff --git a/stubs_thread.cpp b/stubs_thread.cpp index 849e137..e69de29 100644 --- a/stubs_thread.cpp +++ b/stubs_thread.cpp @@ -1,50 +0,0 @@ -#include "mednafen/mednafen-types.h" -#include "mednafen/mednafen.h" -#include "mednafen/md5.h" -#include "mednafen/git.h" -#include "mednafen/general.h" -#include "mednafen/mednafen-driver.h" -#include "thread.h" - -MDFN_Thread *MDFND_CreateThread(int (*fn)(void *), void *data) -{ - return (MDFN_Thread*)sthread_create((void (*)(void*))fn, data); -} - -void MDFND_WaitThread(MDFN_Thread *thr, int *val) -{ - sthread_join((sthread_t*)thr); - - if (val) - { - *val = 0; - fprintf(stderr, "WaitThread relies on return value.\n"); - } -} - -void MDFND_KillThread(MDFN_Thread *) -{ - fprintf(stderr, "Killing a thread is a BAD IDEA!\n"); -} - -MDFN_Mutex *MDFND_CreateMutex() -{ - return (MDFN_Mutex*)slock_new(); -} - -void MDFND_DestroyMutex(MDFN_Mutex *lock) -{ - slock_free((slock_t*)lock); -} - -int MDFND_LockMutex(MDFN_Mutex *lock) -{ - slock_lock((slock_t*)lock); - return 0; -} - -int MDFND_UnlockMutex(MDFN_Mutex *lock) -{ - slock_unlock((slock_t*)lock); - return 0; -} diff --git a/thread.cpp b/thread.cpp deleted file mode 100644 index 85c5a65..0000000 --- a/thread.cpp +++ /dev/null @@ -1,295 +0,0 @@ -/* RetroArch - A frontend for libretro. - * Copyright (C) 2010-2012 - Hans-Kristian Arntzen - * - * RetroArch 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 Found- - * ation, either version 3 of the License, or (at your option) any later version. - * - * RetroArch 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 RetroArch. - * If not, see . - */ - -#include "thread.h" -#include - -#if defined(_WIN32) && !defined(_XBOX) -#define WIN32_LEAN_AND_MEAN -#include -#elif defined(_XBOX) -#include -#elif defined(GEKKO) -#include "thread/gx_pthread.h" -#else -#include -#include -#endif - -#ifdef __MACH__ -#include -#include -#endif - -struct thread_data -{ - void (*func)(void*); - void *userdata; -}; - -#ifdef _WIN32 - -struct sthread -{ - HANDLE thread; -}; - -static DWORD CALLBACK thread_wrap(void *data_) -{ - struct thread_data *data = (struct thread_data*)data_; - data->func(data->userdata); - free(data); - return 0; -} - -sthread_t *sthread_create(void (*thread_func)(void*), void *userdata) -{ - sthread_t *thread = (sthread_t*)calloc(1, sizeof(*thread)); - if (!thread) - return NULL; - - struct thread_data *data = (struct thread_data*)calloc(1, sizeof(*data)); - if (!data) - { - free(thread); - return NULL; - } - - data->func = thread_func; - data->userdata = userdata; - - thread->thread = CreateThread(NULL, 0, thread_wrap, data, 0, NULL); - if (!thread->thread) - { - free(data); - free(thread); - return NULL; - } - - return thread; -} - -void sthread_join(sthread_t *thread) -{ - WaitForSingleObject(thread->thread, INFINITE); - CloseHandle(thread->thread); - free(thread); -} - -struct slock -{ - CRITICAL_SECTION lock; -}; - -slock_t *slock_new(void) -{ - slock_t *lock = (slock_t*)calloc(1, sizeof(*lock)); - if (!lock) - return NULL; - - InitializeCriticalSection(&lock->lock); - return lock; -} - -void slock_free(slock_t *lock) -{ - DeleteCriticalSection(&lock->lock); - free(lock); -} - -void slock_lock(slock_t *lock) -{ - EnterCriticalSection(&lock->lock); -} - -void slock_unlock(slock_t *lock) -{ - LeaveCriticalSection(&lock->lock); -} - -struct scond -{ - HANDLE event; -}; - -scond_t *scond_new(void) -{ - scond_t *cond = (scond_t*)calloc(1, sizeof(*cond)); - if (!cond) - return NULL; - - cond->event = CreateEvent(NULL, FALSE, FALSE, NULL); - if (!cond->event) - { - free(cond); - return NULL; - } - - return cond; -} - -void scond_wait(scond_t *cond, slock_t *lock) -{ - WaitForSingleObject(cond->event, 0); - slock_unlock(lock); - - WaitForSingleObject(cond->event, INFINITE); - - slock_lock(lock); -} - -int scond_wait_timeout(scond_t *cond, slock_t *lock, unsigned timeout_ms) -{ - WaitForSingleObject(cond->event, 0); - slock_unlock(lock); - - DWORD res = WaitForSingleObject(cond->event, timeout_ms); - - slock_lock(lock); - return res == WAIT_OBJECT_0; -} - -void scond_signal(scond_t *cond) -{ - SetEvent(cond->event); -} - -void scond_free(scond_t *cond) -{ - CloseHandle(cond->event); - free(cond); -} - -#else - -struct sthread -{ - pthread_t id; -}; - -static void *thread_wrap(void *data_) -{ - struct thread_data *data = (struct thread_data*)data_; - data->func(data->userdata); - free(data); - return NULL; -} - -sthread_t *sthread_create(void (*thread_func)(void*), void *userdata) -{ - sthread_t *thr = (sthread_t*)calloc(1, sizeof(*thr)); - if (!thr) - return NULL; - - struct thread_data *data = (struct thread_data*)calloc(1, sizeof(*data)); - if (!data) - { - free(thr); - return NULL; - } - - data->func = thread_func; - data->userdata = userdata; - - if (pthread_create(&thr->id, NULL, thread_wrap, data) < 0) - { - free(data); - free(thr); - return NULL; - } - - return thr; -} - -void sthread_join(sthread_t *thread) -{ - pthread_join(thread->id, NULL); - free(thread); -} - -struct slock -{ - pthread_mutex_t lock; -}; - -slock_t *slock_new(void) -{ - slock_t *lock = (slock_t*)calloc(1, sizeof(*lock)); - if (!lock) - return NULL; - - if (pthread_mutex_init(&lock->lock, NULL) < 0) - { - free(lock); - return NULL; - } - - return lock; -} - -void slock_free(slock_t *lock) -{ - pthread_mutex_destroy(&lock->lock); - free(lock); -} - -void slock_lock(slock_t *lock) -{ - pthread_mutex_lock(&lock->lock); -} - -void slock_unlock(slock_t *lock) -{ - pthread_mutex_unlock(&lock->lock); -} - -struct scond -{ - pthread_cond_t cond; -}; - -scond_t *scond_new(void) -{ - scond_t *cond = (scond_t*)calloc(1, sizeof(*cond)); - if (!cond) - return NULL; - - if (pthread_cond_init(&cond->cond, NULL) < 0) - { - free(cond); - return NULL; - } - - return cond; -} - -void scond_free(scond_t *cond) -{ - pthread_cond_destroy(&cond->cond); - free(cond); -} - -void scond_wait(scond_t *cond, slock_t *lock) -{ - pthread_cond_wait(&cond->cond, &lock->lock); -} - -void scond_signal(scond_t *cond) -{ - pthread_cond_signal(&cond->cond); -} - -#endif -