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: */