diff --git a/CMakeLists.txt b/CMakeLists.txt index 7a29d0f4b..42a1a046d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1512,13 +1512,15 @@ elseif(WINDOWS) endif() if(SDL_THREADS) + set(SDL_THREAD_GENERIC_COND_SUFFIX 1) set(SDL_THREAD_WINDOWS 1) set(SOURCE_FILES ${SOURCE_FILES} + ${SDL2_SOURCE_DIR}/src/thread/generic/SDL_syscond.c + ${SDL2_SOURCE_DIR}/src/thread/windows/SDL_syscond_srw.c ${SDL2_SOURCE_DIR}/src/thread/windows/SDL_sysmutex.c ${SDL2_SOURCE_DIR}/src/thread/windows/SDL_syssem.c ${SDL2_SOURCE_DIR}/src/thread/windows/SDL_systhread.c - ${SDL2_SOURCE_DIR}/src/thread/windows/SDL_systls.c - ${SDL2_SOURCE_DIR}/src/thread/generic/SDL_syscond.c) + ${SDL2_SOURCE_DIR}/src/thread/windows/SDL_systls.c) set(HAVE_SDL_THREADS TRUE) endif() diff --git a/VisualC-WinRT/WinPhone81_VS2013/SDL-WinPhone81.vcxproj b/VisualC-WinRT/WinPhone81_VS2013/SDL-WinPhone81.vcxproj index b36d4f111..d684c8e23 100644 --- a/VisualC-WinRT/WinPhone81_VS2013/SDL-WinPhone81.vcxproj +++ b/VisualC-WinRT/WinPhone81_VS2013/SDL-WinPhone81.vcxproj @@ -132,6 +132,7 @@ + @@ -269,6 +270,7 @@ + diff --git a/VisualC-WinRT/WinPhone81_VS2013/SDL-WinPhone81.vcxproj.filters b/VisualC-WinRT/WinPhone81_VS2013/SDL-WinPhone81.vcxproj.filters index a7fe1a6db..0019ae0f1 100644 --- a/VisualC-WinRT/WinPhone81_VS2013/SDL-WinPhone81.vcxproj.filters +++ b/VisualC-WinRT/WinPhone81_VS2013/SDL-WinPhone81.vcxproj.filters @@ -381,6 +381,9 @@ Source Files + + Source Files + Source Files @@ -716,6 +719,9 @@ Source Files + + Source Files + Source Files diff --git a/VisualC-WinRT/WinRT81_VS2013/SDL-WinRT81.vcxproj b/VisualC-WinRT/WinRT81_VS2013/SDL-WinRT81.vcxproj index 9e4fbe768..3d756ceab 100644 --- a/VisualC-WinRT/WinRT81_VS2013/SDL-WinRT81.vcxproj +++ b/VisualC-WinRT/WinRT81_VS2013/SDL-WinRT81.vcxproj @@ -146,6 +146,7 @@ + @@ -303,6 +304,7 @@ + diff --git a/VisualC-WinRT/WinRT81_VS2013/SDL-WinRT81.vcxproj.filters b/VisualC-WinRT/WinRT81_VS2013/SDL-WinRT81.vcxproj.filters index b4dfc7526..aa52d8a5c 100644 --- a/VisualC-WinRT/WinRT81_VS2013/SDL-WinRT81.vcxproj.filters +++ b/VisualC-WinRT/WinRT81_VS2013/SDL-WinRT81.vcxproj.filters @@ -390,6 +390,9 @@ Source Files + + Source Files + Source Files @@ -743,6 +746,9 @@ Source Files + + Source Files + Source Files diff --git a/VisualC/SDL/SDL.vcxproj b/VisualC/SDL/SDL.vcxproj index 0e8b293f6..c5739535d 100644 --- a/VisualC/SDL/SDL.vcxproj +++ b/VisualC/SDL/SDL.vcxproj @@ -359,6 +359,7 @@ + @@ -512,6 +513,7 @@ + diff --git a/VisualC/SDL/SDL.vcxproj.filters b/VisualC/SDL/SDL.vcxproj.filters index f14a8b556..d7cddb140 100644 --- a/VisualC/SDL/SDL.vcxproj.filters +++ b/VisualC/SDL/SDL.vcxproj.filters @@ -301,6 +301,7 @@ + @@ -456,6 +457,7 @@ + diff --git a/configure.ac b/configure.ac index 379f6cfcd..79e783578 100644 --- a/configure.ac +++ b/configure.ac @@ -3869,6 +3869,7 @@ AS_HELP_STRING([--enable-render-d3d], [enable the Direct3D render driver [[defau fi # Set up files for the thread library if test x$enable_threads = xyes; then + AC_DEFINE(SDL_THREAD_GENERIC_COND_SUFFIX, 1, []) AC_DEFINE(SDL_THREAD_WINDOWS, 1, [ ]) SOURCES="$SOURCES $srcdir/src/thread/windows/*.c" SOURCES="$SOURCES $srcdir/src/thread/generic/SDL_syscond.c" diff --git a/include/SDL_config.h.cmake b/include/SDL_config.h.cmake index e3aae654c..f9b109049 100644 --- a/include/SDL_config.h.cmake +++ b/include/SDL_config.h.cmake @@ -330,6 +330,7 @@ #cmakedefine SDL_LOADSO_WINDOWS @SDL_LOADSO_WINDOWS@ /* Enable various threading systems */ +#cmakedefine SDL_THREAD_GENERIC_COND_SUFFIX @SDL_THREAD_GENERIC_COND_SUFFIX@ #cmakedefine SDL_THREAD_PTHREAD @SDL_THREAD_PTHREAD@ #cmakedefine SDL_THREAD_PTHREAD_RECURSIVE_MUTEX @SDL_THREAD_PTHREAD_RECURSIVE_MUTEX@ #cmakedefine SDL_THREAD_PTHREAD_RECURSIVE_MUTEX_NP @SDL_THREAD_PTHREAD_RECURSIVE_MUTEX_NP@ diff --git a/include/SDL_config.h.in b/include/SDL_config.h.in index 07b94f47f..88af73c75 100644 --- a/include/SDL_config.h.in +++ b/include/SDL_config.h.in @@ -331,6 +331,7 @@ #undef SDL_LOADSO_WINDOWS /* Enable various threading systems */ +#undef SDL_THREAD_GENERIC_COND_SUFFIX #undef SDL_THREAD_PTHREAD #undef SDL_THREAD_PTHREAD_RECURSIVE_MUTEX #undef SDL_THREAD_PTHREAD_RECURSIVE_MUTEX_NP diff --git a/include/SDL_config_windows.h b/include/SDL_config_windows.h index 519014874..0eaef9046 100644 --- a/include/SDL_config_windows.h +++ b/include/SDL_config_windows.h @@ -237,6 +237,7 @@ typedef unsigned int uintptr_t; #define SDL_LOADSO_WINDOWS 1 /* Enable various threading systems */ +#define SDL_THREAD_GENERIC_COND_SUFFIX 1 #define SDL_THREAD_WINDOWS 1 /* Enable various timer systems */ diff --git a/include/SDL_config_winrt.h b/include/SDL_config_winrt.h index 2144b79fa..a00185a32 100644 --- a/include/SDL_config_winrt.h +++ b/include/SDL_config_winrt.h @@ -212,6 +212,7 @@ typedef unsigned int uintptr_t; /* Enable various threading systems */ #if (NTDDI_VERSION >= NTDDI_WINBLUE) +#define SDL_THREAD_GENERIC_COND_SUFFIX 1 #define SDL_THREAD_WINDOWS 1 #else /* WinRT on Windows 8.0 and Windows Phone 8.0 don't support CreateThread() */ diff --git a/src/thread/generic/SDL_syscond.c b/src/thread/generic/SDL_syscond.c index 5cd97457a..0e31c2d10 100644 --- a/src/thread/generic/SDL_syscond.c +++ b/src/thread/generic/SDL_syscond.c @@ -28,41 +28,57 @@ #include "SDL_thread.h" -struct SDL_cond +#include "../generic/SDL_syscond_c.h" + +/* If two implementations are to be compiled into SDL (the active one + * will be chosen at runtime), the function names need to be + * suffixed + */ +#if !SDL_THREAD_GENERIC_COND_SUFFIX +#define SDL_CreateCond_generic SDL_CreateCond +#define SDL_DestroyCond_generic SDL_DestroyCond +#define SDL_CondSignal_generic SDL_CondSignal +#define SDL_CondBroadcast_generic SDL_CondBroadcast +#define SDL_CondWait_generic SDL_CondWait +#define SDL_CondWaitTimeout_generic SDL_CondWaitTimeout +#endif + +typedef struct SDL_cond_generic { SDL_mutex *lock; int waiting; int signals; SDL_sem *wait_sem; SDL_sem *wait_done; -}; +} SDL_cond_generic; /* Create a condition variable */ SDL_cond * -SDL_CreateCond(void) +SDL_CreateCond_generic(void) { - SDL_cond *cond; + SDL_cond_generic *cond; - cond = (SDL_cond *) SDL_malloc(sizeof(SDL_cond)); + cond = (SDL_cond_generic *) SDL_malloc(sizeof(SDL_cond_generic)); if (cond) { cond->lock = SDL_CreateMutex(); cond->wait_sem = SDL_CreateSemaphore(0); cond->wait_done = SDL_CreateSemaphore(0); cond->waiting = cond->signals = 0; if (!cond->lock || !cond->wait_sem || !cond->wait_done) { - SDL_DestroyCond(cond); + SDL_DestroyCond_generic((SDL_cond *)cond); cond = NULL; } } else { SDL_OutOfMemory(); } - return (cond); + return (SDL_cond *)cond; } /* Destroy a condition variable */ void -SDL_DestroyCond(SDL_cond * cond) +SDL_DestroyCond_generic(SDL_cond * _cond) { + SDL_cond_generic *cond = (SDL_cond_generic *)_cond; if (cond) { if (cond->wait_sem) { SDL_DestroySemaphore(cond->wait_sem); @@ -79,8 +95,9 @@ SDL_DestroyCond(SDL_cond * cond) /* Restart one of the threads that are waiting on the condition variable */ int -SDL_CondSignal(SDL_cond * cond) +SDL_CondSignal_generic(SDL_cond * _cond) { + SDL_cond_generic *cond = (SDL_cond_generic *)_cond; if (!cond) { return SDL_SetError("Passed a NULL condition variable"); } @@ -103,8 +120,9 @@ SDL_CondSignal(SDL_cond * cond) /* Restart all threads that are waiting on the condition variable */ int -SDL_CondBroadcast(SDL_cond * cond) +SDL_CondBroadcast_generic(SDL_cond * _cond) { + SDL_cond_generic *cond = (SDL_cond_generic *)_cond; if (!cond) { return SDL_SetError("Passed a NULL condition variable"); } @@ -157,8 +175,9 @@ Thread B: SDL_UnlockMutex(lock); */ int -SDL_CondWaitTimeout(SDL_cond * cond, SDL_mutex * mutex, Uint32 ms) +SDL_CondWaitTimeout_generic(SDL_cond * _cond, SDL_mutex * mutex, Uint32 ms) { + SDL_cond_generic *cond = (SDL_cond_generic *)_cond; int retval; if (!cond) { @@ -212,9 +231,9 @@ SDL_CondWaitTimeout(SDL_cond * cond, SDL_mutex * mutex, Uint32 ms) /* Wait on the condition variable forever */ int -SDL_CondWait(SDL_cond * cond, SDL_mutex * mutex) +SDL_CondWait_generic(SDL_cond * cond, SDL_mutex * mutex) { - return SDL_CondWaitTimeout(cond, mutex, SDL_MUTEX_MAXWAIT); + return SDL_CondWaitTimeout_generic(cond, mutex, SDL_MUTEX_MAXWAIT); } /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/thread/generic/SDL_syscond_c.h b/src/thread/generic/SDL_syscond_c.h new file mode 100644 index 000000000..a6f368cad --- /dev/null +++ b/src/thread/generic/SDL_syscond_c.h @@ -0,0 +1,42 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2020 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#include "SDL_thread.h" + +#ifndef SDL_syscond_generic_h_ +#define SDL_syscond_generic_h_ + +#if SDL_THREAD_GENERIC_COND_SUFFIX + +SDL_cond * SDL_CreateCond_generic(void); +void SDL_DestroyCond_generic(SDL_cond * cond); +int SDL_CondSignal_generic(SDL_cond * cond); +int SDL_CondBroadcast_generic(SDL_cond * cond); +int SDL_CondWait_generic(SDL_cond * cond, SDL_mutex * mutex); +int SDL_CondWaitTimeout_generic(SDL_cond * cond, + SDL_mutex * mutex, Uint32 ms); + +#endif /* SDL_THREAD_GENERIC_COND_SUFFIX */ + +#endif /* SDL_syscond_generic_h_ */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/thread/windows/SDL_syscond_srw.c b/src/thread/windows/SDL_syscond_srw.c new file mode 100644 index 000000000..ef8c802f3 --- /dev/null +++ b/src/thread/windows/SDL_syscond_srw.c @@ -0,0 +1,102 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2020 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "../../SDL_internal.h" + +#include "SDL_hints.h" +#include "SDL_thread.h" + +#include "../generic/SDL_syscond_c.h" + +typedef SDL_cond * (*pfnSDL_CreateCond)(void); +typedef void (*pfnSDL_DestroyCond)(SDL_cond *); +typedef int (*pfnSDL_CondSignal)(SDL_cond *); +typedef int (*pfnSDL_CondBroadcast)(SDL_cond *); +typedef int (*pfnSDL_CondWait)(SDL_cond *, SDL_mutex *); +typedef int (*pfnSDL_CondWaitTimeout)(SDL_cond *, SDL_mutex *, Uint32); + +typedef struct SDL_cond_impl_t +{ + pfnSDL_CreateCond Create; + pfnSDL_DestroyCond Destroy; + pfnSDL_CondSignal Signal; + pfnSDL_CondBroadcast Broadcast; + pfnSDL_CondWait Wait; + pfnSDL_CondWaitTimeout WaitTimeout; +} SDL_cond_impl_t; + +/* Implementation will be chosen at runtime based on available Kernel features */ +static SDL_cond_impl_t SDL_cond_impl_active = {0}; + +/** + * Generic Condition Variable implementation using SDL_mutex and SDL_sem + */ + +static const SDL_cond_impl_t SDL_cond_impl_generic = +{ + &SDL_CreateCond_generic, + &SDL_DestroyCond_generic, + &SDL_CondSignal_generic, + &SDL_CondBroadcast_generic, + &SDL_CondWait_generic, + &SDL_CondWaitTimeout_generic, +}; + + +SDL_cond * +SDL_CreateCond(void) +{ + if (SDL_cond_impl_active.Create == NULL) { + SDL_memcpy(&SDL_cond_impl_active, &SDL_cond_impl_generic, sizeof(SDL_cond_impl_active)); + } + return SDL_cond_impl_active.Create(); +} + +void +SDL_DestroyCond(SDL_cond * cond) +{ + SDL_cond_impl_active.Destroy(cond); +} + +int +SDL_CondSignal(SDL_cond * cond) +{ + return SDL_cond_impl_active.Signal(cond); +} + +int +SDL_CondBroadcast(SDL_cond * cond) +{ + return SDL_cond_impl_active.Broadcast(cond); +} + +int +SDL_CondWaitTimeout(SDL_cond * cond, SDL_mutex * mutex, Uint32 ms) +{ + return SDL_cond_impl_active.WaitTimeout(cond, mutex, ms); +} + +int +SDL_CondWait(SDL_cond * cond, SDL_mutex * mutex) +{ + return SDL_cond_impl_active.Wait(cond, mutex); +} + +/* vi: set ts=4 sw=4 expandtab: */