Implemented an API for thread-local storage: SDL_TLSCreate(), SDL_TLSSet(), SDL_TLSGet()
This commit is contained in:
parent
ab91b4ce14
commit
bfcb08d569
14 changed files with 618 additions and 156 deletions
|
@ -1132,6 +1132,10 @@
|
|||
RelativePath="..\..\src\thread\windows\SDL_systhread.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\thread\windows\SDL_systls.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\thread\SDL_systhread.h"
|
||||
>
|
||||
|
|
|
@ -438,6 +438,7 @@
|
|||
<ClCompile Include="..\..\src\power\windows\SDL_syspower.c" />
|
||||
<ClCompile Include="..\..\src\thread\windows\SDL_syssem.c" />
|
||||
<ClCompile Include="..\..\src\thread\windows\SDL_systhread.c" />
|
||||
<ClCompile Include="..\..\src\thread\windows\SDL_systls.c" />
|
||||
<ClCompile Include="..\..\src\timer\windows\SDL_systimer.c" />
|
||||
<ClCompile Include="..\..\src\thread\SDL_thread.c" />
|
||||
<ClCompile Include="..\..\src\timer\SDL_timer.c" />
|
||||
|
@ -462,4 +463,4 @@
|
|||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
|
|
@ -441,6 +441,7 @@
|
|||
<ClCompile Include="..\..\src\power\windows\SDL_syspower.c" />
|
||||
<ClCompile Include="..\..\src\thread\windows\SDL_syssem.c" />
|
||||
<ClCompile Include="..\..\src\thread\windows\SDL_systhread.c" />
|
||||
<ClCompile Include="..\..\src\thread\windows\SDL_systls.c" />
|
||||
<ClCompile Include="..\..\src\timer\windows\SDL_systimer.c" />
|
||||
<ClCompile Include="..\..\src\thread\SDL_thread.c" />
|
||||
<ClCompile Include="..\..\src\timer\SDL_timer.c" />
|
||||
|
@ -466,4 +467,4 @@
|
|||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
|
|
@ -76,6 +76,7 @@
|
|||
93CB792613FC5F5300BD3E05 /* SDL_uikitviewcontroller.m in Sources */ = {isa = PBXBuildFile; fileRef = 93CB792513FC5F5300BD3E05 /* SDL_uikitviewcontroller.m */; };
|
||||
AA0AD06216647BBB00CE5896 /* SDL_gamecontroller.c in Sources */ = {isa = PBXBuildFile; fileRef = AA0AD06116647BBB00CE5896 /* SDL_gamecontroller.c */; };
|
||||
AA0AD06516647BD400CE5896 /* SDL_gamecontroller.h in Headers */ = {isa = PBXBuildFile; fileRef = AA0AD06416647BD400CE5896 /* SDL_gamecontroller.h */; };
|
||||
AA0F8495178D5F1A00823F9D /* SDL_systls.c in Sources */ = {isa = PBXBuildFile; fileRef = AA0F8494178D5F1A00823F9D /* SDL_systls.c */; };
|
||||
AA126AD41617C5E7005ABC8F /* SDL_uikitmodes.h in Headers */ = {isa = PBXBuildFile; fileRef = AA126AD21617C5E6005ABC8F /* SDL_uikitmodes.h */; };
|
||||
AA126AD51617C5E7005ABC8F /* SDL_uikitmodes.m in Sources */ = {isa = PBXBuildFile; fileRef = AA126AD31617C5E6005ABC8F /* SDL_uikitmodes.m */; };
|
||||
AA628ADB159369E3005138DD /* SDL_rotate.c in Sources */ = {isa = PBXBuildFile; fileRef = AA628AD9159369E3005138DD /* SDL_rotate.c */; };
|
||||
|
@ -268,6 +269,7 @@
|
|||
93CB792513FC5F5300BD3E05 /* SDL_uikitviewcontroller.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDL_uikitviewcontroller.m; sourceTree = "<group>"; };
|
||||
AA0AD06116647BBB00CE5896 /* SDL_gamecontroller.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_gamecontroller.c; sourceTree = "<group>"; };
|
||||
AA0AD06416647BD400CE5896 /* SDL_gamecontroller.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_gamecontroller.h; sourceTree = "<group>"; };
|
||||
AA0F8494178D5F1A00823F9D /* SDL_systls.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_systls.c; sourceTree = "<group>"; };
|
||||
AA126AD21617C5E6005ABC8F /* SDL_uikitmodes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_uikitmodes.h; sourceTree = "<group>"; };
|
||||
AA126AD31617C5E6005ABC8F /* SDL_uikitmodes.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDL_uikitmodes.m; sourceTree = "<group>"; };
|
||||
AA628AD9159369E3005138DD /* SDL_rotate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_rotate.c; sourceTree = "<group>"; };
|
||||
|
@ -851,6 +853,7 @@
|
|||
FD99BA0A0DD52EDC00FB1D6B /* SDL_syssem.c */,
|
||||
FD99BA0B0DD52EDC00FB1D6B /* SDL_systhread.c */,
|
||||
FD99BA0C0DD52EDC00FB1D6B /* SDL_systhread_c.h */,
|
||||
AA0F8494178D5F1A00823F9D /* SDL_systls.c */,
|
||||
);
|
||||
path = pthread;
|
||||
sourceTree = "<group>";
|
||||
|
@ -1189,6 +1192,7 @@
|
|||
AA704DD7162AA90A0076D1C1 /* SDL_dropevents.c in Sources */,
|
||||
AABCC3951640643D00AB8930 /* SDL_uikitmessagebox.m in Sources */,
|
||||
AA0AD06216647BBB00CE5896 /* SDL_gamecontroller.c in Sources */,
|
||||
AA0F8495178D5F1A00823F9D /* SDL_systls.c in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
|
@ -398,6 +398,9 @@
|
|||
A77E6EB4167AB0A90010E40B /* SDL_gamecontroller.h in Headers */ = {isa = PBXBuildFile; fileRef = A77E6EB3167AB0A90010E40B /* SDL_gamecontroller.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
A77E6EB5167AB0A90010E40B /* SDL_gamecontroller.h in Headers */ = {isa = PBXBuildFile; fileRef = A77E6EB3167AB0A90010E40B /* SDL_gamecontroller.h */; };
|
||||
AA0AD09D16648D1700CE5896 /* SDL_gamecontroller.c in Sources */ = {isa = PBXBuildFile; fileRef = BBFC088A164C6514003E6A99 /* SDL_gamecontroller.c */; };
|
||||
AA0F8491178D5ECC00823F9D /* SDL_systls.c in Sources */ = {isa = PBXBuildFile; fileRef = AA0F8490178D5ECC00823F9D /* SDL_systls.c */; };
|
||||
AA0F8492178D5ECC00823F9D /* SDL_systls.c in Sources */ = {isa = PBXBuildFile; fileRef = AA0F8490178D5ECC00823F9D /* SDL_systls.c */; };
|
||||
AA0F8493178D5ECC00823F9D /* SDL_systls.c in Sources */ = {isa = PBXBuildFile; fileRef = AA0F8490178D5ECC00823F9D /* SDL_systls.c */; };
|
||||
AA41F88014B8F1F500993C4F /* SDL_dropevents.c in Sources */ = {isa = PBXBuildFile; fileRef = 566CDE8E148F0AC200C5A9BB /* SDL_dropevents.c */; };
|
||||
AA628ACA159367B7005138DD /* SDL_rotate.c in Sources */ = {isa = PBXBuildFile; fileRef = AA628AC8159367B7005138DD /* SDL_rotate.c */; };
|
||||
AA628ACB159367B7005138DD /* SDL_rotate.c in Sources */ = {isa = PBXBuildFile; fileRef = AA628AC8159367B7005138DD /* SDL_rotate.c */; };
|
||||
|
@ -984,6 +987,7 @@
|
|||
566CDE8D148F0AC200C5A9BB /* SDL_dropevents_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_dropevents_c.h; sourceTree = "<group>"; };
|
||||
566CDE8E148F0AC200C5A9BB /* SDL_dropevents.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_dropevents.c; sourceTree = "<group>"; };
|
||||
A77E6EB3167AB0A90010E40B /* SDL_gamecontroller.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_gamecontroller.h; sourceTree = "<group>"; };
|
||||
AA0F8490178D5ECC00823F9D /* SDL_systls.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_systls.c; sourceTree = "<group>"; };
|
||||
AA628AC8159367B7005138DD /* SDL_rotate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_rotate.c; sourceTree = "<group>"; };
|
||||
AA628AC9159367B7005138DD /* SDL_rotate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_rotate.h; sourceTree = "<group>"; };
|
||||
AA628ACF159367F2005138DD /* SDL_x11xinput2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_x11xinput2.c; sourceTree = "<group>"; };
|
||||
|
@ -1462,6 +1466,7 @@
|
|||
04BDFE8112E6671800899322 /* SDL_syssem.c */,
|
||||
04BDFE8212E6671800899322 /* SDL_systhread.c */,
|
||||
04BDFE8312E6671800899322 /* SDL_systhread_c.h */,
|
||||
AA0F8490178D5ECC00823F9D /* SDL_systls.c */,
|
||||
);
|
||||
path = pthread;
|
||||
sourceTree = "<group>";
|
||||
|
@ -2403,6 +2408,7 @@
|
|||
AA9E4093163BE51E007A2AD0 /* SDL_x11messagebox.c in Sources */,
|
||||
AABCC38F164063D200AB8930 /* SDL_cocoamessagebox.m in Sources */,
|
||||
AA0AD09D16648D1700CE5896 /* SDL_gamecontroller.c in Sources */,
|
||||
AA0F8491178D5ECC00823F9D /* SDL_systls.c in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -2519,6 +2525,7 @@
|
|||
AA628AD2159367F2005138DD /* SDL_x11xinput2.c in Sources */,
|
||||
AA9E4094163BE51E007A2AD0 /* SDL_x11messagebox.c in Sources */,
|
||||
AABCC390164063D200AB8930 /* SDL_cocoamessagebox.m in Sources */,
|
||||
AA0F8492178D5ECC00823F9D /* SDL_systls.c in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -2635,6 +2642,7 @@
|
|||
DB31406817554B71006C0E22 /* SDL_x11xinput2.c in Sources */,
|
||||
DB31406917554B71006C0E22 /* SDL_x11messagebox.c in Sources */,
|
||||
DB31406A17554B71006C0E22 /* SDL_cocoamessagebox.m in Sources */,
|
||||
AA0F8493178D5ECC00823F9D /* SDL_systls.c in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
25
configure
vendored
25
configure
vendored
|
@ -1511,7 +1511,7 @@ Optional Features:
|
|||
--enable-sse use SSE assembly routines [[default=yes]]
|
||||
--enable-sse2 use SSE2 assembly routines [[default=no]]
|
||||
--enable-altivec use Altivec assembly routines [[default=yes]]
|
||||
--enable-oss support the OSS audio API [[default=yes]]
|
||||
--enable-oss support the OSS audio API [[default=maybe]]
|
||||
--enable-alsa support the ALSA audio API [[default=yes]]
|
||||
--disable-alsatest Do not try to compile and run a test Alsa program
|
||||
--enable-alsa-shared dynamically load ALSA audio support [[default=yes]]
|
||||
|
@ -17535,9 +17535,21 @@ CheckOSS()
|
|||
if test "${enable_oss+set}" = set; then :
|
||||
enableval=$enable_oss;
|
||||
else
|
||||
enable_oss=yes
|
||||
enable_oss=maybe
|
||||
fi
|
||||
|
||||
|
||||
# OpenBSD "has" OSS, but it's not really for app use. They want you to
|
||||
# use sndio instead. So on there, we default to disabled. You can force
|
||||
# it on if you really want, though.
|
||||
if test x$enable_oss = xmaybe; then
|
||||
enable_oss=yes
|
||||
case "$host" in
|
||||
*-*-openbsd*)
|
||||
enable_oss=no;;
|
||||
esac
|
||||
fi
|
||||
|
||||
if test x$enable_audio = xyes -a x$enable_oss = xyes; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for OSS audio support" >&5
|
||||
$as_echo_n "checking for OSS audio support... " >&6; }
|
||||
|
@ -21423,6 +21435,9 @@ $as_echo "$has_pthread_set_name_np" >&6; }
|
|||
# We can fake these with semaphores and mutexes if necessary
|
||||
SOURCES="$SOURCES $srcdir/src/thread/pthread/SDL_syscond.c"
|
||||
|
||||
# Thread local storage
|
||||
SOURCES="$SOURCES $srcdir/src/thread/pthread/SDL_systls.c"
|
||||
|
||||
have_threads=yes
|
||||
fi
|
||||
fi
|
||||
|
@ -22206,7 +22221,7 @@ $as_echo "#define SDL_AUDIO_DRIVER_SUNAUDIO 1" >>confdefs.h
|
|||
SOURCES="$SOURCES $srcdir/src/audio/sun/*.c"
|
||||
have_audio=yes
|
||||
;;
|
||||
netbsd|openbsd)
|
||||
netbsd) # Don't use this on OpenBSD, it's busted.
|
||||
|
||||
$as_echo "#define SDL_AUDIO_DRIVER_BSD 1" >>confdefs.h
|
||||
|
||||
|
@ -22367,9 +22382,7 @@ $as_echo "#define SDL_POWER_WINDOWS 1" >>confdefs.h
|
|||
|
||||
$as_echo "#define SDL_THREAD_WINDOWS 1" >>confdefs.h
|
||||
|
||||
SOURCES="$SOURCES $srcdir/src/thread/windows/SDL_sysmutex.c"
|
||||
SOURCES="$SOURCES $srcdir/src/thread/windows/SDL_syssem.c"
|
||||
SOURCES="$SOURCES $srcdir/src/thread/windows/SDL_systhread.c"
|
||||
SOURCES="$SOURCES $srcdir/src/thread/windows/*.c"
|
||||
SOURCES="$SOURCES $srcdir/src/thread/generic/SDL_syscond.c"
|
||||
have_threads=yes
|
||||
fi
|
||||
|
|
|
@ -657,6 +657,7 @@ AC_HELP_STRING([--enable-oss], [support the OSS audio API [[default=maybe]]]),
|
|||
case "$host" in
|
||||
*-*-openbsd*)
|
||||
enable_oss=no;;
|
||||
esac
|
||||
fi
|
||||
|
||||
if test x$enable_audio = xyes -a x$enable_oss = xyes; then
|
||||
|
@ -2019,6 +2020,9 @@ AC_HELP_STRING([--enable-pthread-sem], [use pthread semaphores [[default=yes]]])
|
|||
# We can fake these with semaphores and mutexes if necessary
|
||||
SOURCES="$SOURCES $srcdir/src/thread/pthread/SDL_syscond.c"
|
||||
|
||||
# Thread local storage
|
||||
SOURCES="$SOURCES $srcdir/src/thread/pthread/SDL_systls.c"
|
||||
|
||||
have_threads=yes
|
||||
fi
|
||||
fi
|
||||
|
@ -2470,9 +2474,7 @@ AC_HELP_STRING([--enable-render-d3d], [enable the Direct3D render driver [[defau
|
|||
# Set up files for the thread library
|
||||
if test x$enable_threads = xyes; then
|
||||
AC_DEFINE(SDL_THREAD_WINDOWS, 1, [ ])
|
||||
SOURCES="$SOURCES $srcdir/src/thread/windows/SDL_sysmutex.c"
|
||||
SOURCES="$SOURCES $srcdir/src/thread/windows/SDL_syssem.c"
|
||||
SOURCES="$SOURCES $srcdir/src/thread/windows/SDL_systhread.c"
|
||||
SOURCES="$SOURCES $srcdir/src/thread/windows/*.c"
|
||||
SOURCES="$SOURCES $srcdir/src/thread/generic/SDL_syscond.c"
|
||||
have_threads=yes
|
||||
fi
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "SDL_error.h"
|
||||
|
||||
/* Thread synchronization primitives */
|
||||
#include "SDL_atomic.h"
|
||||
#include "SDL_mutex.h"
|
||||
|
||||
#include "begin_code.h"
|
||||
|
@ -47,6 +48,9 @@ typedef struct SDL_Thread SDL_Thread;
|
|||
/* The SDL thread ID */
|
||||
typedef unsigned long SDL_threadID;
|
||||
|
||||
/* Thread local storage ID */
|
||||
typedef int SDL_TLSID;
|
||||
|
||||
/* The SDL thread priority
|
||||
*
|
||||
* Note: On many systems you require special privileges to set high priority.
|
||||
|
@ -166,6 +170,63 @@ extern DECLSPEC int SDLCALL SDL_SetThreadPriority(SDL_ThreadPriority priority);
|
|||
*/
|
||||
extern DECLSPEC void SDLCALL SDL_WaitThread(SDL_Thread * thread, int *status);
|
||||
|
||||
/**
|
||||
* \brief Create an identifier that is globally visible to all threads but refers to data that is thread-specific.
|
||||
*
|
||||
* \return The newly created thread local storage identifier, or 0 on error
|
||||
*
|
||||
* \code
|
||||
* static SDL_SpinLock tls_lock;
|
||||
* static SDL_TLSID thread_local_storage;
|
||||
*
|
||||
* void SetMyThreadData(void *value)
|
||||
* {
|
||||
* if (!thread_local_storage) {
|
||||
* SDL_AtomicLock(&tls_lock);
|
||||
* if (!thread_local_storage) {
|
||||
* thread_local_storage = SDL_TLSCreate();
|
||||
* }
|
||||
* SDL_AtomicUnLock(&tls_lock);
|
||||
* }
|
||||
* SDL_TLSSet(thread_local_storage, value);
|
||||
* }
|
||||
*
|
||||
* void *GetMyThreadData(void)
|
||||
* {
|
||||
* return SDL_TLSGet(thread_local_storage);
|
||||
* }
|
||||
* \endcode
|
||||
*
|
||||
* \sa SDL_TLSGet()
|
||||
* \sa SDL_TLSSet()
|
||||
*/
|
||||
extern DECLSPEC SDL_TLSID SDLCALL SDL_TLSCreate();
|
||||
|
||||
/**
|
||||
* \brief Get the value associated with a thread local storage ID for the current thread.
|
||||
*
|
||||
* \param id The thread local storage ID
|
||||
*
|
||||
* \return The value associated with the ID for the current thread, or NULL if no value has been set.
|
||||
*
|
||||
* \sa SDL_TLSCreate()
|
||||
* \sa SDL_TLSSet()
|
||||
*/
|
||||
extern DECLSPEC void * SDLCALL SDL_TLSGet(SDL_TLSID id);
|
||||
|
||||
/**
|
||||
* \brief Set the value associated with a thread local storage ID for the current thread.
|
||||
*
|
||||
* \param id The thread local storage ID
|
||||
* \param value The value to associate with the ID for the current thread
|
||||
*
|
||||
* \return 0 on success, -1 on error
|
||||
*
|
||||
* \sa SDL_TLSCreate()
|
||||
* \sa SDL_TLSGet()
|
||||
*/
|
||||
extern DECLSPEC int SDLCALL SDL_TLSSet(SDL_TLSID id, const void *value);
|
||||
|
||||
|
||||
/* Ends C function definitions when using C++ */
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -22,158 +22,46 @@
|
|||
|
||||
/* System independent thread management routines for SDL */
|
||||
|
||||
#include "SDL_mutex.h"
|
||||
#include "SDL_thread.h"
|
||||
#include "SDL_thread_c.h"
|
||||
#include "SDL_systhread.h"
|
||||
#include "../SDL_error_c.h"
|
||||
|
||||
#define ARRAY_CHUNKSIZE 32
|
||||
/* The array of threads currently active in the application
|
||||
(except the main thread)
|
||||
The manipulation of an array here is safer than using a linked list.
|
||||
*/
|
||||
static int SDL_maxthreads = 0;
|
||||
static int SDL_numthreads = 0;
|
||||
static SDL_Thread **SDL_Threads = NULL;
|
||||
static SDL_mutex *thread_lock = NULL;
|
||||
|
||||
static int
|
||||
SDL_ThreadsInit(void)
|
||||
{
|
||||
int retval;
|
||||
|
||||
retval = 0;
|
||||
thread_lock = SDL_CreateMutex();
|
||||
if (thread_lock == NULL) {
|
||||
retval = -1;
|
||||
}
|
||||
return (retval);
|
||||
}
|
||||
|
||||
/* This should never be called...
|
||||
If this is called by SDL_Quit(), we don't know whether or not we should
|
||||
clean up threads here. If any threads are still running after this call,
|
||||
they will no longer have access to any per-thread data.
|
||||
*/
|
||||
#if 0
|
||||
static void
|
||||
SDL_ThreadsQuit(void)
|
||||
{
|
||||
SDL_mutex *mutex;
|
||||
|
||||
mutex = thread_lock;
|
||||
thread_lock = NULL;
|
||||
if (mutex != NULL) {
|
||||
SDL_DestroyMutex(mutex);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Routines for manipulating the thread list */
|
||||
static void
|
||||
SDL_AddThread(SDL_Thread * thread)
|
||||
{
|
||||
/* WARNING:
|
||||
If the very first threads are created simultaneously, then
|
||||
there could be a race condition causing memory corruption.
|
||||
In practice, this isn't a problem because by definition there
|
||||
is only one thread running the first time this is called.
|
||||
*/
|
||||
if (!thread_lock) {
|
||||
if (SDL_ThreadsInit() < 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
SDL_LockMutex(thread_lock);
|
||||
|
||||
/* Expand the list of threads, if necessary */
|
||||
#ifdef DEBUG_THREADS
|
||||
printf("Adding thread (%d already - %d max)\n",
|
||||
SDL_numthreads, SDL_maxthreads);
|
||||
#endif
|
||||
if (SDL_numthreads == SDL_maxthreads) {
|
||||
SDL_Thread **threads;
|
||||
threads = (SDL_Thread **) SDL_realloc(SDL_Threads,
|
||||
(SDL_maxthreads +
|
||||
ARRAY_CHUNKSIZE) *
|
||||
(sizeof *threads));
|
||||
if (threads == NULL) {
|
||||
SDL_OutOfMemory();
|
||||
goto done;
|
||||
}
|
||||
SDL_maxthreads += ARRAY_CHUNKSIZE;
|
||||
SDL_Threads = threads;
|
||||
}
|
||||
SDL_Threads[SDL_numthreads++] = thread;
|
||||
done:
|
||||
SDL_mutexV(thread_lock);
|
||||
}
|
||||
|
||||
static void
|
||||
SDL_DelThread(SDL_Thread * thread)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!thread_lock) {
|
||||
return;
|
||||
}
|
||||
SDL_LockMutex(thread_lock);
|
||||
for (i = 0; i < SDL_numthreads; ++i) {
|
||||
if (thread == SDL_Threads[i]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i < SDL_numthreads) {
|
||||
if (--SDL_numthreads > 0) {
|
||||
while (i < SDL_numthreads) {
|
||||
SDL_Threads[i] = SDL_Threads[i + 1];
|
||||
++i;
|
||||
}
|
||||
} else {
|
||||
SDL_maxthreads = 0;
|
||||
SDL_free(SDL_Threads);
|
||||
SDL_Threads = NULL;
|
||||
}
|
||||
#ifdef DEBUG_THREADS
|
||||
printf("Deleting thread (%d left - %d max)\n",
|
||||
SDL_numthreads, SDL_maxthreads);
|
||||
#endif
|
||||
}
|
||||
SDL_mutexV(thread_lock);
|
||||
|
||||
#if 0 /* There could be memory corruption if another thread is starting */
|
||||
if (SDL_Threads == NULL) {
|
||||
SDL_ThreadsQuit();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* The default (non-thread-safe) global error variable */
|
||||
static SDL_error SDL_global_error;
|
||||
|
||||
/* Routine to get the thread-specific error variable */
|
||||
SDL_error *
|
||||
SDL_GetErrBuf(void)
|
||||
{
|
||||
static SDL_SpinLock spinlock;
|
||||
static SDL_bool tls_being_created;
|
||||
static SDL_TLSID tls_errbuf;
|
||||
static SDL_error SDL_global_errbuf;
|
||||
SDL_error *errbuf;
|
||||
|
||||
errbuf = &SDL_global_error;
|
||||
if (SDL_Threads) {
|
||||
int i;
|
||||
SDL_threadID this_thread;
|
||||
|
||||
this_thread = SDL_ThreadID();
|
||||
SDL_LockMutex(thread_lock);
|
||||
for (i = 0; i < SDL_numthreads; ++i) {
|
||||
if (this_thread == SDL_Threads[i]->threadid) {
|
||||
errbuf = &SDL_Threads[i]->errbuf;
|
||||
break;
|
||||
}
|
||||
if (!tls_errbuf && !tls_being_created) {
|
||||
SDL_AtomicLock(&spinlock);
|
||||
if (!tls_errbuf) {
|
||||
/* SDL_TLSCreate() could fail and call SDL_SetError() */
|
||||
tls_being_created = SDL_TRUE;
|
||||
tls_errbuf = SDL_TLSCreate();
|
||||
tls_being_created = SDL_FALSE;
|
||||
}
|
||||
SDL_mutexV(thread_lock);
|
||||
SDL_AtomicUnlock(&spinlock);
|
||||
}
|
||||
return (errbuf);
|
||||
if (!tls_errbuf) {
|
||||
return &SDL_global_errbuf;
|
||||
}
|
||||
|
||||
errbuf = SDL_TLSGet(tls_errbuf);
|
||||
if (!errbuf) {
|
||||
errbuf = (SDL_error *)SDL_malloc(sizeof(*errbuf));
|
||||
if (!errbuf) {
|
||||
return &SDL_global_errbuf;
|
||||
}
|
||||
SDL_zerop(errbuf);
|
||||
SDL_TLSSet(tls_errbuf, errbuf);
|
||||
}
|
||||
return errbuf;
|
||||
}
|
||||
|
||||
|
||||
|
@ -264,9 +152,6 @@ SDL_CreateThread(int (SDLCALL * fn) (void *),
|
|||
return (NULL);
|
||||
}
|
||||
|
||||
/* Add the thread to the list of available threads */
|
||||
SDL_AddThread(thread);
|
||||
|
||||
/* Create the thread and go! */
|
||||
#ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
|
||||
ret = SDL_SYS_CreateThread(thread, args, pfnBeginThread, pfnEndThread);
|
||||
|
@ -278,7 +163,6 @@ SDL_CreateThread(int (SDLCALL * fn) (void *),
|
|||
SDL_SemWait(args->wait);
|
||||
} else {
|
||||
/* Oops, failed. Gotta free everything */
|
||||
SDL_DelThread(thread);
|
||||
SDL_free(thread->name);
|
||||
SDL_free(thread);
|
||||
thread = NULL;
|
||||
|
@ -323,7 +207,6 @@ SDL_WaitThread(SDL_Thread * thread, int *status)
|
|||
if (status) {
|
||||
*status = thread->status;
|
||||
}
|
||||
SDL_DelThread(thread);
|
||||
SDL_free(thread->name);
|
||||
SDL_free(thread);
|
||||
}
|
||||
|
|
106
src/thread/beos/SDL_systls.c
Normal file
106
src/thread/beos/SDL_systls.c
Normal file
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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_config.h"
|
||||
#include "SDL_thread.h"
|
||||
|
||||
#if SDL_THREAD_BEOS
|
||||
|
||||
#include <support/TLS.h>
|
||||
|
||||
|
||||
#define TLS_ALLOC_CHUNKSIZE 8
|
||||
|
||||
typedef struct {
|
||||
int limit;
|
||||
void *data[1];
|
||||
} SDL_TLSData;
|
||||
|
||||
static SDL_SpinLock tls_lock;
|
||||
static int32 thread_local_storage = B_NO_MEMORY;
|
||||
static SDL_atomic_t tls_id;
|
||||
|
||||
|
||||
SDL_TLSID
|
||||
SDL_TLSCreate()
|
||||
{
|
||||
if (thread_local_storage == B_NO_MEMORY) {
|
||||
SDL_AtomicLock(&tls_lock);
|
||||
if (thread_local_storage == B_NO_MEMORY) {
|
||||
thread_local_storage = tls_allocate();
|
||||
if (thread_local_storage == B_NO_MEMORY) {
|
||||
SDL_SetError("tls_allocate() failed");
|
||||
SDL_AtomicUnlock(&tls_lock);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
SDL_AtomicUnlock(&tls_lock);
|
||||
}
|
||||
return SDL_AtomicIncRef(&tls_id)+1;
|
||||
}
|
||||
|
||||
void *
|
||||
SDL_TLSGet(SDL_TLSID id)
|
||||
{
|
||||
SDL_TLSData *data;
|
||||
|
||||
data = (SDL_TLSData *)tls_get(thread_local_storage);
|
||||
if (!data || id <= 0 || id > data->limit) {
|
||||
return NULL;
|
||||
}
|
||||
return data->data[id-1];
|
||||
}
|
||||
|
||||
int
|
||||
SDL_TLSSet(SDL_TLSID id, const void *value)
|
||||
{
|
||||
SDL_TLSData *data;
|
||||
|
||||
if (thread_local_storage == B_NO_MEMORY || id <= 0) {
|
||||
return SDL_InvalidParamError(id);
|
||||
}
|
||||
|
||||
data = (SDL_TLSData *)tls_get(thread_local_storage);
|
||||
if (!data || id > data->limit) {
|
||||
int i, oldlimit, newlimit;
|
||||
|
||||
oldlimit = data ? data->limit : 0;
|
||||
newlimit = (id + TLS_ALLOC_CHUNKSIZE);
|
||||
data = (SDL_TLSData *)SDL_realloc(data, sizeof(*data)+(newlimit-1)*sizeof(void*));
|
||||
if (!data) {
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
data->limit = newlimit;
|
||||
for (i = oldlimit; i < newlimit; ++i) {
|
||||
data->data[i] = NULL;
|
||||
}
|
||||
if (!tls_set(thread_local_storage, data)) {
|
||||
return SDL_SetError("TlsSetValue() failed");
|
||||
}
|
||||
}
|
||||
|
||||
data->data[id-1] = SDL_const_cast(void*, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* SDL_THREAD_BEOS */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
163
src/thread/generic/SDL_systls.c
Normal file
163
src/thread/generic/SDL_systls.c
Normal file
|
@ -0,0 +1,163 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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_config.h"
|
||||
#include "SDL_thread.h"
|
||||
|
||||
/* This is a generic implementation of thread-local storage which doesn't
|
||||
require additional OS support.
|
||||
|
||||
It is not especially efficient and doesn't clean up thread-local storage
|
||||
as threads exit. If there is a real OS that doesn't support thread-local
|
||||
storage this implementation should be improved to be production quality.
|
||||
*/
|
||||
|
||||
#define TLS_ALLOC_CHUNKSIZE 8
|
||||
|
||||
typedef struct {
|
||||
int limit;
|
||||
void *data[1];
|
||||
} SDL_TLSData;
|
||||
|
||||
typedef struct SDL_TLSEntry {
|
||||
SDL_threadID thread;
|
||||
SDL_TLSData *data;
|
||||
struct SDL_TLSEntry *next;
|
||||
} SDL_TLSEntry;
|
||||
|
||||
static SDL_SpinLock tls_lock;
|
||||
static SDL_mutex *tls_mutex;
|
||||
static SDL_TLSEntry *thread_local_storage;
|
||||
static SDL_atomic_t tls_id;
|
||||
|
||||
|
||||
static SDL_TLSData *GetTLSData()
|
||||
{
|
||||
SDL_threadID thread = SDL_ThreadID();
|
||||
SDL_TLSEntry *entry;
|
||||
SDL_TLSData *data = NULL;
|
||||
|
||||
if (!tls_mutex) {
|
||||
SDL_AtomicLock(&tls_lock);
|
||||
if (!tls_mutex) {
|
||||
tls_mutex = SDL_CreateMutex();
|
||||
if (!tls_mutex) {
|
||||
SDL_AtomicUnlock(&tls_lock);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
SDL_AtomicUnlock(&tls_lock);
|
||||
}
|
||||
|
||||
SDL_LockMutex(tls_mutex);
|
||||
for (entry = thread_local_storage; entry; entry = entry->next) {
|
||||
if (entry->thread == thread) {
|
||||
data = entry->data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
SDL_UnlockMutex(tls_mutex);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static int SetTLSData(SDL_TLSData *data)
|
||||
{
|
||||
SDL_threadID thread = SDL_ThreadID();
|
||||
SDL_TLSEntry *entry;
|
||||
|
||||
/* GetTLSData() is always called first, so we can assume tls_mutex */
|
||||
SDL_LockMutex(tls_mutex);
|
||||
for (entry = thread_local_storage; entry; entry = entry->next) {
|
||||
if (entry->thread == thread) {
|
||||
entry->data = data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!entry) {
|
||||
entry = (SDL_TLSEntry *)SDL_malloc(sizeof(*entry));
|
||||
if (entry) {
|
||||
entry->thread = thread;
|
||||
entry->data = data;
|
||||
entry->next = thread_local_storage;
|
||||
thread_local_storage = entry;
|
||||
}
|
||||
}
|
||||
SDL_UnlockMutex(tls_mutex);
|
||||
|
||||
if (!entry) {
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
SDL_TLSID
|
||||
SDL_TLSCreate()
|
||||
{
|
||||
return SDL_AtomicIncRef(&tls_id)+1;
|
||||
}
|
||||
|
||||
void *
|
||||
SDL_TLSGet(SDL_TLSID id)
|
||||
{
|
||||
SDL_TLSData *data;
|
||||
|
||||
data = GetTLSData();
|
||||
if (!data || id <= 0 || id > data->limit) {
|
||||
return NULL;
|
||||
}
|
||||
return data->data[id-1];
|
||||
}
|
||||
|
||||
int
|
||||
SDL_TLSSet(SDL_TLSID id, const void *value)
|
||||
{
|
||||
SDL_TLSData *data;
|
||||
|
||||
if (id <= 0) {
|
||||
return SDL_InvalidParamError(id);
|
||||
}
|
||||
|
||||
data = GetTLSData();
|
||||
if (!data || id > data->limit) {
|
||||
int i, oldlimit, newlimit;
|
||||
|
||||
oldlimit = data ? data->limit : 0;
|
||||
newlimit = (id + TLS_ALLOC_CHUNKSIZE);
|
||||
data = (SDL_TLSData *)SDL_realloc(data, sizeof(*data)+(newlimit-1)*sizeof(void*));
|
||||
if (!data) {
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
data->limit = newlimit;
|
||||
for (i = oldlimit; i < newlimit; ++i) {
|
||||
data->data[i] = NULL;
|
||||
}
|
||||
if (SetTLSData(data) != 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
data->data[id-1] = SDL_const_cast(void*, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
101
src/thread/pthread/SDL_systls.c
Normal file
101
src/thread/pthread/SDL_systls.c
Normal file
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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_config.h"
|
||||
#include "SDL_thread.h"
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
#define TLS_ALLOC_CHUNKSIZE 8
|
||||
|
||||
typedef struct {
|
||||
int limit;
|
||||
void *data[1];
|
||||
} SDL_TLSData;
|
||||
|
||||
static SDL_SpinLock tls_lock;
|
||||
static pthread_key_t thread_local_storage;
|
||||
static SDL_atomic_t tls_id;
|
||||
|
||||
|
||||
SDL_TLSID
|
||||
SDL_TLSCreate()
|
||||
{
|
||||
if (!thread_local_storage) {
|
||||
SDL_AtomicLock(&tls_lock);
|
||||
if (!thread_local_storage) {
|
||||
if (pthread_key_create(&thread_local_storage, NULL) != 0) {
|
||||
SDL_SetError("pthread_key_create() failed");
|
||||
SDL_AtomicUnlock(&tls_lock);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
SDL_AtomicUnlock(&tls_lock);
|
||||
}
|
||||
return SDL_AtomicIncRef(&tls_id)+1;
|
||||
}
|
||||
|
||||
void *
|
||||
SDL_TLSGet(SDL_TLSID id)
|
||||
{
|
||||
SDL_TLSData *data;
|
||||
|
||||
data = (SDL_TLSData *)pthread_getspecific(thread_local_storage);
|
||||
if (!data || id <= 0 || id > data->limit) {
|
||||
return NULL;
|
||||
}
|
||||
return data->data[id-1];
|
||||
}
|
||||
|
||||
int
|
||||
SDL_TLSSet(SDL_TLSID id, const void *value)
|
||||
{
|
||||
SDL_TLSData *data;
|
||||
|
||||
if (!thread_local_storage || id <= 0) {
|
||||
return SDL_InvalidParamError(id);
|
||||
}
|
||||
|
||||
data = (SDL_TLSData *)pthread_getspecific(thread_local_storage);
|
||||
if (!data || id > data->limit) {
|
||||
int i, oldlimit, newlimit;
|
||||
|
||||
oldlimit = data ? data->limit : 0;
|
||||
newlimit = (id + TLS_ALLOC_CHUNKSIZE);
|
||||
data = (SDL_TLSData *)SDL_realloc(data, sizeof(*data)+(newlimit-1)*sizeof(void*));
|
||||
if (!data) {
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
data->limit = newlimit;
|
||||
for (i = oldlimit; i < newlimit; ++i) {
|
||||
data->data[i] = NULL;
|
||||
}
|
||||
if (pthread_setspecific(thread_local_storage, data) != 0) {
|
||||
return SDL_SetError("pthread_setspecific() failed");
|
||||
}
|
||||
}
|
||||
|
||||
data->data[id-1] = SDL_const_cast(void*, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
106
src/thread/windows/SDL_systls.c
Normal file
106
src/thread/windows/SDL_systls.c
Normal file
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
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_config.h"
|
||||
#include "SDL_thread.h"
|
||||
|
||||
#if SDL_THREAD_WINDOWS
|
||||
|
||||
#include "../../core/windows/SDL_windows.h"
|
||||
|
||||
|
||||
#define TLS_ALLOC_CHUNKSIZE 8
|
||||
|
||||
typedef struct {
|
||||
int limit;
|
||||
void *data[1];
|
||||
} SDL_TLSData;
|
||||
|
||||
static SDL_SpinLock tls_lock;
|
||||
static DWORD thread_local_storage = TLS_OUT_OF_INDEXES;
|
||||
static SDL_atomic_t tls_id;
|
||||
|
||||
|
||||
SDL_TLSID
|
||||
SDL_TLSCreate()
|
||||
{
|
||||
if (thread_local_storage == TLS_OUT_OF_INDEXES) {
|
||||
SDL_AtomicLock(&tls_lock);
|
||||
if (thread_local_storage == TLS_OUT_OF_INDEXES) {
|
||||
thread_local_storage = TlsAlloc();
|
||||
if (thread_local_storage == TLS_OUT_OF_INDEXES) {
|
||||
SDL_SetError("TlsAlloc() failed");
|
||||
SDL_AtomicUnlock(&tls_lock);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
SDL_AtomicUnlock(&tls_lock);
|
||||
}
|
||||
return SDL_AtomicIncRef(&tls_id)+1;
|
||||
}
|
||||
|
||||
void *
|
||||
SDL_TLSGet(SDL_TLSID id)
|
||||
{
|
||||
SDL_TLSData *data;
|
||||
|
||||
data = (SDL_TLSData *)TlsGetValue(thread_local_storage);
|
||||
if (!data || id <= 0 || id > data->limit) {
|
||||
return NULL;
|
||||
}
|
||||
return data->data[id-1];
|
||||
}
|
||||
|
||||
int
|
||||
SDL_TLSSet(SDL_TLSID id, const void *value)
|
||||
{
|
||||
SDL_TLSData *data;
|
||||
|
||||
if (thread_local_storage == TLS_OUT_OF_INDEXES || id <= 0) {
|
||||
return SDL_InvalidParamError(id);
|
||||
}
|
||||
|
||||
data = (SDL_TLSData *)TlsGetValue(thread_local_storage);
|
||||
if (!data || id > data->limit) {
|
||||
int i, oldlimit, newlimit;
|
||||
|
||||
oldlimit = data ? data->limit : 0;
|
||||
newlimit = (id + TLS_ALLOC_CHUNKSIZE);
|
||||
data = (SDL_TLSData *)SDL_realloc(data, sizeof(*data)+(newlimit-1)*sizeof(void*));
|
||||
if (!data) {
|
||||
return SDL_OutOfMemory();
|
||||
}
|
||||
data->limit = newlimit;
|
||||
for (i = oldlimit; i < newlimit; ++i) {
|
||||
data->data[i] = NULL;
|
||||
}
|
||||
if (!TlsSetValue(thread_local_storage, data)) {
|
||||
return SDL_SetError("TlsSetValue() failed");
|
||||
}
|
||||
}
|
||||
|
||||
data->data[id-1] = SDL_const_cast(void*, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* SDL_THREAD_WINDOWS */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
|
@ -19,6 +19,7 @@
|
|||
#include "SDL.h"
|
||||
#include "SDL_thread.h"
|
||||
|
||||
static SDL_TLSID tls;
|
||||
static int alive = 0;
|
||||
|
||||
/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
|
||||
|
@ -32,8 +33,9 @@ quit(int rc)
|
|||
int SDLCALL
|
||||
ThreadFunc(void *data)
|
||||
{
|
||||
printf("Started thread %s: My thread id is %lu\n",
|
||||
(char *) data, SDL_ThreadID());
|
||||
SDL_TLSSet(tls, "baby thread");
|
||||
printf("Started thread %s: My thread id is %lu, thread data = %s\n",
|
||||
(char *) data, SDL_ThreadID(), (const char *)SDL_TLSGet(tls));
|
||||
while (alive) {
|
||||
printf("Thread '%s' is alive!\n", (char *) data);
|
||||
SDL_Delay(1 * 1000);
|
||||
|
@ -62,6 +64,11 @@ main(int argc, char *argv[])
|
|||
return (1);
|
||||
}
|
||||
|
||||
tls = SDL_TLSCreate();
|
||||
SDL_assert(tls);
|
||||
SDL_TLSSet(tls, "main thread");
|
||||
printf("Main thread data initially: %s\n", (const char *)SDL_TLSGet(tls));
|
||||
|
||||
alive = 1;
|
||||
thread = SDL_CreateThread(ThreadFunc, "One", "#1");
|
||||
if (thread == NULL) {
|
||||
|
@ -73,6 +80,8 @@ main(int argc, char *argv[])
|
|||
alive = 0;
|
||||
SDL_WaitThread(thread, NULL);
|
||||
|
||||
printf("Main thread data finally: %s\n", (const char *)SDL_TLSGet(tls));
|
||||
|
||||
alive = 1;
|
||||
signal(SIGTERM, killed);
|
||||
thread = SDL_CreateThread(ThreadFunc, "Two", "#2");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue