Added SDL_DetachThread() API.

This commit is contained in:
Ryan C. Gordon
2013-11-14 00:52:39 -05:00
parent 7550ddcc05
commit 8d6e03f353
8 changed files with 118 additions and 5 deletions

View File

@@ -51,6 +51,9 @@ extern int SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority);
*/
extern void SDL_SYS_WaitThread(SDL_Thread * thread);
/* Mark thread as cleaned up as soon as it exits, without joining. */
extern void SDL_SYS_DetachThread(SDL_Thread * thread);
/* Get the thread local storage for this thread */
extern SDL_TLSData *SDL_SYS_GetTLSData();

View File

@@ -22,6 +22,7 @@
/* System independent thread management routines for SDL */
#include "SDL_assert.h"
#include "SDL_thread.h"
#include "SDL_thread_c.h"
#include "SDL_systhread.h"
@@ -265,13 +266,14 @@ SDL_RunThread(void *data)
thread_args *args = (thread_args *) data;
int (SDLCALL * userfunc) (void *) = args->func;
void *userdata = args->data;
int *statusloc = &args->info->status;
SDL_Thread *thread = args->info;
int *statusloc = &thread->status;
/* Perform any system-dependent setup - this function may not fail */
SDL_SYS_SetupThread(args->info->name);
SDL_SYS_SetupThread(thread->name);
/* Get the thread id */
args->info->threadid = SDL_ThreadID();
thread->threadid = SDL_ThreadID();
/* Wake up the parent thread */
SDL_SemPost(args->wait);
@@ -281,6 +283,17 @@ SDL_RunThread(void *data)
/* Clean up thread-local storage */
SDL_TLSCleanup();
/* Mark us as ready to be joined (or detached) */
if (!SDL_AtomicCAS(&thread->state, SDL_THREAD_STATE_ALIVE, SDL_THREAD_STATE_ZOMBIE)) {
/* Clean up if something already detached us. */
if (SDL_AtomicCAS(&thread->state, SDL_THREAD_STATE_DETACHED, SDL_THREAD_STATE_CLEANED)) {
if (thread->name) {
SDL_free(thread->name);
}
SDL_free(thread);
}
}
}
#ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
@@ -306,8 +319,9 @@ SDL_CreateThread(int (SDLCALL * fn) (void *),
SDL_OutOfMemory();
return (NULL);
}
SDL_memset(thread, 0, (sizeof *thread));
SDL_zerop(thread);
thread->status = -1;
SDL_AtomicSet(&thread->state, SDL_THREAD_STATE_ALIVE);
/* Set up the arguments for the thread */
if (name != NULL) {
@@ -410,4 +424,27 @@ SDL_WaitThread(SDL_Thread * thread, int *status)
}
}
void
SDL_DetachThread(SDL_Thread * thread)
{
if (!thread) {
return;
}
/* Grab dibs if the state is alive+joinable. */
if (SDL_AtomicCAS(&thread->state, SDL_THREAD_STATE_ALIVE, SDL_THREAD_STATE_DETACHED)) {
SDL_SYS_DetachThread(thread);
} else {
/* all other states are pretty final, see where we landed. */
const int state = SDL_AtomicGet(&thread->state);
if ((state == SDL_THREAD_STATE_DETACHED) || (state == SDL_THREAD_STATE_CLEANED)) {
return; /* already detached (you shouldn't call this twice!) */
} else if (state == SDL_THREAD_STATE_ZOMBIE) {
SDL_WaitThread(thread, NULL); /* already done, clean it up. */
} else {
SDL_assert(0 && "Unexpected thread state");
}
}
}
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -40,12 +40,21 @@
#endif
#include "../SDL_error_c.h"
typedef enum SDL_ThreadState
{
SDL_THREAD_STATE_ALIVE,
SDL_THREAD_STATE_DETACHED,
SDL_THREAD_STATE_ZOMBIE,
SDL_THREAD_STATE_CLEANED,
} SDL_ThreadState;
/* This is the system-independent thread info structure */
struct SDL_Thread
{
SDL_threadID threadid;
SYS_ThreadHandle handle;
int status;
SDL_atomic_t state; /* SDL_THREAD_STATE_* */
SDL_error errbuf;
char *name;
void *data;

View File

@@ -62,4 +62,10 @@ SDL_SYS_WaitThread(SDL_Thread * thread)
return;
}
void
SDL_SYS_DetachThread(SDL_Thread * thread)
{
return;
}
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -77,6 +77,12 @@ void SDL_SYS_WaitThread(SDL_Thread *thread)
sceKernelDeleteThread(thread->handle);
}
void SDL_SYS_DetachThread(SDL_Thread *thread)
{
/* !!! FIXME: is this correct? */
sceKernelDeleteThread(thread->handle);
}
void SDL_SYS_KillThread(SDL_Thread *thread)
{
sceKernelTerminateDeleteThread(thread->handle);

View File

@@ -213,4 +213,10 @@ SDL_SYS_WaitThread(SDL_Thread * thread)
pthread_join(thread->handle, 0);
}
void
SDL_SYS_DetachThread(SDL_Thread * thread)
{
pthread_detach(thread->handle);
}
/* vi: set ts=4 sw=4 expandtab: */

View File

@@ -234,6 +234,12 @@ SDL_SYS_WaitThread(SDL_Thread * thread)
CloseHandle(thread->handle);
}
void
SDL_SYS_DetachThread(SDL_Thread * thread)
{
CloseHandle(thread->handle);
}
#endif /* SDL_THREAD_WINDOWS */
/* vi: set ts=4 sw=4 expandtab: */