src/thread/SDL_thread.c
changeset 7978 70ac84e49797
parent 7730 e928464b98ec
child 8093 b43765095a6f
     1.1 --- a/src/thread/SDL_thread.c	Wed Nov 13 22:35:26 2013 -0500
     1.2 +++ b/src/thread/SDL_thread.c	Thu Nov 14 00:52:39 2013 -0500
     1.3 @@ -22,6 +22,7 @@
     1.4  
     1.5  /* System independent thread management routines for SDL */
     1.6  
     1.7 +#include "SDL_assert.h"
     1.8  #include "SDL_thread.h"
     1.9  #include "SDL_thread_c.h"
    1.10  #include "SDL_systhread.h"
    1.11 @@ -265,13 +266,14 @@
    1.12      thread_args *args = (thread_args *) data;
    1.13      int (SDLCALL * userfunc) (void *) = args->func;
    1.14      void *userdata = args->data;
    1.15 -    int *statusloc = &args->info->status;
    1.16 +    SDL_Thread *thread = args->info;
    1.17 +    int *statusloc = &thread->status;
    1.18  
    1.19      /* Perform any system-dependent setup - this function may not fail */
    1.20 -    SDL_SYS_SetupThread(args->info->name);
    1.21 +    SDL_SYS_SetupThread(thread->name);
    1.22  
    1.23      /* Get the thread id */
    1.24 -    args->info->threadid = SDL_ThreadID();
    1.25 +    thread->threadid = SDL_ThreadID();
    1.26  
    1.27      /* Wake up the parent thread */
    1.28      SDL_SemPost(args->wait);
    1.29 @@ -281,6 +283,17 @@
    1.30  
    1.31      /* Clean up thread-local storage */
    1.32      SDL_TLSCleanup();
    1.33 +
    1.34 +    /* Mark us as ready to be joined (or detached) */
    1.35 +    if (!SDL_AtomicCAS(&thread->state, SDL_THREAD_STATE_ALIVE, SDL_THREAD_STATE_ZOMBIE)) {
    1.36 +        /* Clean up if something already detached us. */
    1.37 +        if (SDL_AtomicCAS(&thread->state, SDL_THREAD_STATE_DETACHED, SDL_THREAD_STATE_CLEANED)) {
    1.38 +            if (thread->name) {
    1.39 +                SDL_free(thread->name);
    1.40 +            }
    1.41 +            SDL_free(thread);
    1.42 +        }
    1.43 +    }
    1.44  }
    1.45  
    1.46  #ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
    1.47 @@ -306,8 +319,9 @@
    1.48          SDL_OutOfMemory();
    1.49          return (NULL);
    1.50      }
    1.51 -    SDL_memset(thread, 0, (sizeof *thread));
    1.52 +    SDL_zerop(thread);
    1.53      thread->status = -1;
    1.54 +    SDL_AtomicSet(&thread->state, SDL_THREAD_STATE_ALIVE);
    1.55  
    1.56      /* Set up the arguments for the thread */
    1.57      if (name != NULL) {
    1.58 @@ -410,4 +424,27 @@
    1.59      }
    1.60  }
    1.61  
    1.62 +void
    1.63 +SDL_DetachThread(SDL_Thread * thread)
    1.64 +{
    1.65 +    if (!thread) {
    1.66 +        return;
    1.67 +    }
    1.68 +
    1.69 +    /* Grab dibs if the state is alive+joinable. */
    1.70 +    if (SDL_AtomicCAS(&thread->state, SDL_THREAD_STATE_ALIVE, SDL_THREAD_STATE_DETACHED)) {
    1.71 +        SDL_SYS_DetachThread(thread);
    1.72 +    } else {
    1.73 +        /* all other states are pretty final, see where we landed. */
    1.74 +        const int state = SDL_AtomicGet(&thread->state);
    1.75 +        if ((state == SDL_THREAD_STATE_DETACHED) || (state == SDL_THREAD_STATE_CLEANED)) {
    1.76 +            return;  /* already detached (you shouldn't call this twice!) */
    1.77 +        } else if (state == SDL_THREAD_STATE_ZOMBIE) {
    1.78 +            SDL_WaitThread(thread, NULL);  /* already done, clean it up. */
    1.79 +        } else {
    1.80 +            SDL_assert(0 && "Unexpected thread state");
    1.81 +        }
    1.82 +    }
    1.83 +}
    1.84 +
    1.85  /* vi: set ts=4 sw=4 expandtab: */