SDL  2.0
SDL_thread.c File Reference
#include "../SDL_internal.h"
#include "SDL_assert.h"
#include "SDL_thread.h"
#include "SDL_thread_c.h"
#include "SDL_systhread.h"
#include "SDL_hints.h"
#include "../SDL_error_c.h"
+ Include dependency graph for SDL_thread.c:

Go to the source code of this file.

Data Structures

struct  SDL_TLSEntry
 
struct  thread_args
 

Macros

#define SDL_CreateThread   SDL_CreateThread_REAL
 

Functions

SDL_TLSID SDL_TLSCreate ()
 Create an identifier that is globally visible to all threads but refers to data that is thread-specific. More...
 
voidSDL_TLSGet (SDL_TLSID id)
 Get the value associated with a thread local storage ID for the current thread. More...
 
int SDL_TLSSet (SDL_TLSID id, const void *value, void(*destructor)(void *))
 Set the value associated with a thread local storage ID for the current thread. More...
 
static void SDL_TLSCleanup ()
 
SDL_TLSDataSDL_Generic_GetTLSData (void)
 
int SDL_Generic_SetTLSData (SDL_TLSData *storage)
 
SDL_errorSDL_GetErrBuf (void)
 
void SDL_RunThread (void *data)
 
static SDL_ThreadSDL_CreateThreadWithStackSize (int(*fn)(void *), const char *name, const size_t stacksize, void *data)
 
SDL_ThreadSDL_CreateThread (int(*fn)(void *), const char *name, void *data)
 
SDL_ThreadSDL_CreateThreadInternal (int(*fn)(void *), const char *name, const size_t stacksize, void *data)
 
SDL_threadID SDL_GetThreadID (SDL_Thread *thread)
 
const char * SDL_GetThreadName (SDL_Thread *thread)
 
int SDL_SetThreadPriority (SDL_ThreadPriority priority)
 
void SDL_WaitThread (SDL_Thread *thread, int *status)
 
void SDL_DetachThread (SDL_Thread *thread)
 

Variables

static SDL_mutexSDL_generic_TLS_mutex
 
static SDL_TLSEntrySDL_generic_TLS
 

Macro Definition Documentation

◆ SDL_CreateThread

#define SDL_CreateThread   SDL_CreateThread_REAL

Definition at line 304 of file SDL_thread.c.

Referenced by SDL_CreateThreadWithStackSize().

Function Documentation

◆ SDL_CreateThread()

SDL_Thread* SDL_CreateThread ( int(*)(void *)  fn,
const char *  name,
void data 
)

Definition at line 400 of file SDL_thread.c.

References NULL, SDL_CreateThreadWithStackSize(), SDL_GetHint, SDL_HINT_THREAD_STACK_SIZE, and SDL_strtoll.

403 {
404  /* !!! FIXME: in 2.1, just make stackhint part of the usual API. */
405  const char *stackhint = SDL_GetHint(SDL_HINT_THREAD_STACK_SIZE);
406  size_t stacksize = 0;
407 
408  /* If the SDL_HINT_THREAD_STACK_SIZE exists, use it */
409  if (stackhint != NULL) {
410  char *endp = NULL;
411  const Sint64 hintval = SDL_strtoll(stackhint, &endp, 10);
412  if ((*stackhint != '\0') && (*endp == '\0')) { /* a valid number? */
413  if (hintval > 0) { /* reject bogus values. */
414  stacksize = (size_t) hintval;
415  }
416  }
417  }
418 
419 #ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
420  return SDL_CreateThreadWithStackSize(fn, name, stacksize, data, pfnBeginThread, pfnEndThread);
421 #else
422  return SDL_CreateThreadWithStackSize(fn, name, stacksize, data);
423 #endif
424 }
#define SDL_HINT_THREAD_STACK_SIZE
A string specifying SDL's threads stack size in bytes or "0" for the backend's default size...
Definition: SDL_hints.h:531
#define SDL_GetHint
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
GLuint const GLchar * name
unsigned int size_t
#define NULL
Definition: begin_code.h:164
static SDL_Thread * SDL_CreateThreadWithStackSize(int(*fn)(void *), const char *name, const size_t stacksize, void *data)
Definition: SDL_thread.c:315
#define SDL_strtoll
int64_t Sint64
Definition: SDL_stdinc.h:188

◆ SDL_CreateThreadInternal()

SDL_Thread* SDL_CreateThreadInternal ( int(*)(void *)  fn,
const char *  name,
const size_t  stacksize,
void data 
)

Definition at line 427 of file SDL_thread.c.

References NULL, and SDL_CreateThreadWithStackSize().

Referenced by open_audio_device(), and SDL_TimerInit().

428  {
429 #ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
430  return SDL_CreateThreadWithStackSize(fn, name, stacksize, data, NULL, NULL);
431 #else
432  return SDL_CreateThreadWithStackSize(fn, name, stacksize, data);
433 #endif
434 }
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
GLuint const GLchar * name
#define NULL
Definition: begin_code.h:164
static SDL_Thread * SDL_CreateThreadWithStackSize(int(*fn)(void *), const char *name, const size_t stacksize, void *data)
Definition: SDL_thread.c:315

◆ SDL_CreateThreadWithStackSize()

static SDL_Thread* SDL_CreateThreadWithStackSize ( int(*)(void *)  fn,
const char *  name,
const size_t  stacksize,
void data 
)
static

Definition at line 315 of file SDL_thread.c.

References thread_args::data, DECLSPEC, thread_args::func, thread_args::info, SDL_Thread::name, NULL, SDL_AtomicSet, SDL_CreateSemaphore, SDL_CreateThread, SDL_DestroySemaphore, SDL_free, SDL_malloc, SDL_OutOfMemory, SDL_SemWait, SDL_strdup, SDL_SYS_CreateThread(), SDL_THREAD_STATE_ALIVE, SDL_zerop, SDLCALL, SDL_Thread::stacksize, SDL_Thread::state, SDL_Thread::status, SDL_TLSEntry::thread, and thread_args::wait.

Referenced by SDL_CreateThread(), and SDL_CreateThreadInternal().

318 {
319  SDL_Thread *thread;
320  thread_args *args;
321  int ret;
322 
323  /* Allocate memory for the thread info structure */
324  thread = (SDL_Thread *) SDL_malloc(sizeof(*thread));
325  if (thread == NULL) {
326  SDL_OutOfMemory();
327  return (NULL);
328  }
329  SDL_zerop(thread);
330  thread->status = -1;
332 
333  /* Set up the arguments for the thread */
334  if (name != NULL) {
335  thread->name = SDL_strdup(name);
336  if (thread->name == NULL) {
337  SDL_OutOfMemory();
338  SDL_free(thread);
339  return (NULL);
340  }
341  }
342 
343  /* Set up the arguments for the thread */
344  args = (thread_args *) SDL_malloc(sizeof(*args));
345  if (args == NULL) {
346  SDL_OutOfMemory();
347  if (thread->name) {
348  SDL_free(thread->name);
349  }
350  SDL_free(thread);
351  return (NULL);
352  }
353  args->func = fn;
354  args->data = data;
355  args->info = thread;
356  args->wait = SDL_CreateSemaphore(0);
357  if (args->wait == NULL) {
358  if (thread->name) {
359  SDL_free(thread->name);
360  }
361  SDL_free(thread);
362  SDL_free(args);
363  return (NULL);
364  }
365 
366  thread->stacksize = stacksize;
367 
368  /* Create the thread and go! */
369 #ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
370  ret = SDL_SYS_CreateThread(thread, args, pfnBeginThread, pfnEndThread);
371 #else
372  ret = SDL_SYS_CreateThread(thread, args);
373 #endif
374  if (ret >= 0) {
375  /* Wait for the thread function to use arguments */
376  SDL_SemWait(args->wait);
377  } else {
378  /* Oops, failed. Gotta free everything */
379  if (thread->name) {
380  SDL_free(thread->name);
381  }
382  SDL_free(thread);
383  thread = NULL;
384  }
385  SDL_DestroySemaphore(args->wait);
386  SDL_free(args);
387 
388  /* Everything is running now */
389  return (thread);
390 }
SDL_atomic_t state
Definition: SDL_thread_c.h:59
char * name
Definition: SDL_thread_c.h:61
#define SDL_CreateSemaphore
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
#define SDL_zerop(x)
Definition: SDL_stdinc.h:417
GLuint const GLchar * name
#define SDL_free
int(* func)(void *)
Definition: SDL_thread.c:258
#define NULL
Definition: begin_code.h:164
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_Thread * info
Definition: SDL_thread.c:260
SDL_sem * wait
Definition: SDL_thread.c:261
#define SDL_strdup
#define SDL_SemWait
#define SDL_DestroySemaphore
#define SDL_AtomicSet
#define SDL_malloc
void * data
Definition: SDL_thread.c:259
int SDL_SYS_CreateThread(SDL_Thread *thread, void *args)
Definition: SDL_systhread.c:35
size_t stacksize
Definition: SDL_thread_c.h:62

◆ SDL_DetachThread()

void SDL_DetachThread ( SDL_Thread thread)

A thread may be "detached" to signify that it should not remain until another thread has called SDL_WaitThread() on it. Detaching a thread is useful for long-running threads that nothing needs to synchronize with or further manage. When a detached thread is done, it simply goes away.

There is no way to recover the return code of a detached thread. If you need this, don't detach the thread and instead use SDL_WaitThread().

Once a thread is detached, you should usually assume the SDL_Thread isn't safe to reference again, as it will become invalid immediately upon the detached thread's exit, instead of remaining until someone has called SDL_WaitThread() to finally clean it up. As such, don't detach the same thread more than once.

If a thread has already exited when passed to SDL_DetachThread(), it will stop waiting for a call to SDL_WaitThread() and clean up immediately. It is not safe to detach a thread that might be used with SDL_WaitThread().

You may not call SDL_WaitThread() on a thread that has been detached. Use either that function or this one, but not both, or behavior is undefined.

It is safe to pass NULL to this function; it is a no-op.

Definition at line 481 of file SDL_thread.c.

References NULL, SDL_assert, SDL_AtomicCAS, SDL_AtomicGet, SDL_SYS_DetachThread(), SDL_THREAD_STATE_ALIVE, SDL_THREAD_STATE_CLEANED, SDL_THREAD_STATE_DETACHED, SDL_THREAD_STATE_ZOMBIE, SDL_WaitThread(), and SDL_Thread::state.

482 {
483  if (!thread) {
484  return;
485  }
486 
487  /* Grab dibs if the state is alive+joinable. */
489  SDL_SYS_DetachThread(thread);
490  } else {
491  /* all other states are pretty final, see where we landed. */
492  const int thread_state = SDL_AtomicGet(&thread->state);
493  if ((thread_state == SDL_THREAD_STATE_DETACHED) || (thread_state == SDL_THREAD_STATE_CLEANED)) {
494  return; /* already detached (you shouldn't call this twice!) */
495  } else if (thread_state == SDL_THREAD_STATE_ZOMBIE) {
496  SDL_WaitThread(thread, NULL); /* already done, clean it up. */
497  } else {
498  SDL_assert(0 && "Unexpected thread state");
499  }
500  }
501 }
SDL_atomic_t state
Definition: SDL_thread_c.h:59
#define SDL_AtomicCAS
void SDL_SYS_DetachThread(SDL_Thread *thread)
Definition: SDL_systhread.c:66
#define SDL_assert(condition)
Definition: SDL_assert.h:169
#define NULL
Definition: begin_code.h:164
void SDL_WaitThread(SDL_Thread *thread, int *status)
Definition: SDL_thread.c:466
#define SDL_AtomicGet

◆ SDL_Generic_GetTLSData()

SDL_TLSData* SDL_Generic_GetTLSData ( void  )

Definition at line 124 of file SDL_thread.c.

References mutex, SDL_TLSEntry::next, NULL, SDL_AtomicLock, SDL_AtomicUnlock, SDL_CreateMutex, SDL_LockMutex, SDL_MemoryBarrierAcquire, SDL_MemoryBarrierRelease, SDL_ThreadID, SDL_UnlockMutex, SDL_TLSEntry::storage, and SDL_TLSEntry::thread.

Referenced by SDL_SYS_GetTLSData().

125 {
126  SDL_threadID thread = SDL_ThreadID();
127  SDL_TLSEntry *entry;
128  SDL_TLSData *storage = NULL;
129 
130 #if !SDL_THREADS_DISABLED
131  if (!SDL_generic_TLS_mutex) {
132  static SDL_SpinLock tls_lock;
133  SDL_AtomicLock(&tls_lock);
134  if (!SDL_generic_TLS_mutex) {
138  if (!SDL_generic_TLS_mutex) {
139  SDL_AtomicUnlock(&tls_lock);
140  return NULL;
141  }
142  }
143  SDL_AtomicUnlock(&tls_lock);
144  }
145 #endif /* SDL_THREADS_DISABLED */
146 
149  for (entry = SDL_generic_TLS; entry; entry = entry->next) {
150  if (entry->thread == thread) {
151  storage = entry->storage;
152  break;
153  }
154  }
155 #if !SDL_THREADS_DISABLED
157 #endif
158 
159  return storage;
160 }
#define SDL_ThreadID
SDL_TLSData * storage
Definition: SDL_thread.c:115
#define SDL_LockMutex
static SDL_mutex * SDL_generic_TLS_mutex
Definition: SDL_thread.c:119
#define SDL_AtomicLock
#define SDL_MemoryBarrierRelease()
Definition: SDL_atomic.h:189
#define SDL_CreateMutex
SDL_threadID thread
Definition: SDL_thread.c:114
static SDL_mutex * mutex
Definition: testlock.c:23
#define SDL_MemoryBarrierAcquire()
Definition: SDL_atomic.h:190
struct SDL_TLSEntry * next
Definition: SDL_thread.c:116
#define SDL_AtomicUnlock
Definition: SDL_thread.c:113
#define NULL
Definition: begin_code.h:164
static SDL_TLSEntry * SDL_generic_TLS
Definition: SDL_thread.c:120
#define SDL_UnlockMutex
int SDL_SpinLock
Definition: SDL_atomic.h:89
unsigned long SDL_threadID
Definition: SDL_thread.h:49

◆ SDL_Generic_SetTLSData()

int SDL_Generic_SetTLSData ( SDL_TLSData storage)

Definition at line 163 of file SDL_thread.c.

References SDL_TLSEntry::next, NULL, SDL_free, SDL_generic_TLS, SDL_LockMutex, SDL_malloc, SDL_OutOfMemory, SDL_ThreadID, SDL_UnlockMutex, SDL_TLSEntry::storage, and SDL_TLSEntry::thread.

Referenced by SDL_SYS_SetTLSData().

164 {
165  SDL_threadID thread = SDL_ThreadID();
166  SDL_TLSEntry *prev, *entry;
167 
168  /* SDL_Generic_GetTLSData() is always called first, so we can assume SDL_generic_TLS_mutex */
170  prev = NULL;
171  for (entry = SDL_generic_TLS; entry; entry = entry->next) {
172  if (entry->thread == thread) {
173  if (storage) {
174  entry->storage = storage;
175  } else {
176  if (prev) {
177  prev->next = entry->next;
178  } else {
179  SDL_generic_TLS = entry->next;
180  }
181  SDL_free(entry);
182  }
183  break;
184  }
185  prev = entry;
186  }
187  if (!entry) {
188  entry = (SDL_TLSEntry *)SDL_malloc(sizeof(*entry));
189  if (entry) {
190  entry->thread = thread;
191  entry->storage = storage;
192  entry->next = SDL_generic_TLS;
193  SDL_generic_TLS = entry;
194  }
195  }
197 
198  if (!entry) {
199  return SDL_OutOfMemory();
200  }
201  return 0;
202 }
#define SDL_ThreadID
SDL_TLSData * storage
Definition: SDL_thread.c:115
#define SDL_LockMutex
static SDL_mutex * SDL_generic_TLS_mutex
Definition: SDL_thread.c:119
SDL_threadID thread
Definition: SDL_thread.c:114
struct SDL_TLSEntry * next
Definition: SDL_thread.c:116
#define SDL_free
Definition: SDL_thread.c:113
#define NULL
Definition: begin_code.h:164
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
static SDL_TLSEntry * SDL_generic_TLS
Definition: SDL_thread.c:120
#define SDL_UnlockMutex
#define SDL_malloc
unsigned long SDL_threadID
Definition: SDL_thread.h:49

◆ SDL_GetErrBuf()

SDL_error* SDL_GetErrBuf ( void  )

Definition at line 206 of file SDL_thread.c.

References NULL, SDL_AtomicLock, SDL_AtomicUnlock, SDL_FALSE, SDL_free, SDL_malloc, SDL_MemoryBarrierAcquire, SDL_MemoryBarrierRelease, SDL_TLSCreate(), SDL_TLSGet(), SDL_TLSSet(), SDL_TRUE, and SDL_zerop.

Referenced by SDL_ClearError(), SDL_GetErrorMsg(), and SDL_SetError().

207 {
208  static SDL_SpinLock tls_lock;
209  static SDL_bool tls_being_created;
210  static SDL_TLSID tls_errbuf;
211  static SDL_error SDL_global_errbuf;
212  const SDL_error *ALLOCATION_IN_PROGRESS = (SDL_error *)-1;
213  SDL_error *errbuf;
214 
215  /* tls_being_created is there simply to prevent recursion if SDL_TLSCreate() fails.
216  It also means it's possible for another thread to also use SDL_global_errbuf,
217  but that's very unlikely and hopefully won't cause issues.
218  */
219  if (!tls_errbuf && !tls_being_created) {
220  SDL_AtomicLock(&tls_lock);
221  if (!tls_errbuf) {
222  SDL_TLSID slot;
223  tls_being_created = SDL_TRUE;
224  slot = SDL_TLSCreate();
225  tls_being_created = SDL_FALSE;
227  tls_errbuf = slot;
228  }
229  SDL_AtomicUnlock(&tls_lock);
230  }
231  if (!tls_errbuf) {
232  return &SDL_global_errbuf;
233  }
234 
236  errbuf = (SDL_error *)SDL_TLSGet(tls_errbuf);
237  if (errbuf == ALLOCATION_IN_PROGRESS) {
238  return &SDL_global_errbuf;
239  }
240  if (!errbuf) {
241  /* Mark that we're in the middle of allocating our buffer */
242  SDL_TLSSet(tls_errbuf, ALLOCATION_IN_PROGRESS, NULL);
243  errbuf = (SDL_error *)SDL_malloc(sizeof(*errbuf));
244  if (!errbuf) {
245  SDL_TLSSet(tls_errbuf, NULL, NULL);
246  return &SDL_global_errbuf;
247  }
248  SDL_zerop(errbuf);
249  SDL_TLSSet(tls_errbuf, errbuf, SDL_free);
250  }
251  return errbuf;
252 }
int SDL_TLSSet(SDL_TLSID id, const void *value, void(*destructor)(void *))
Set the value associated with a thread local storage ID for the current thread.
Definition: SDL_thread.c:53
#define SDL_AtomicLock
#define SDL_MemoryBarrierRelease()
Definition: SDL_atomic.h:189
void * SDL_TLSGet(SDL_TLSID id)
Get the value associated with a thread local storage ID for the current thread.
Definition: SDL_thread.c:41
#define SDL_zerop(x)
Definition: SDL_stdinc.h:417
#define SDL_MemoryBarrierAcquire()
Definition: SDL_atomic.h:190
unsigned int SDL_TLSID
Definition: SDL_thread.h:52
#define SDL_AtomicUnlock
#define SDL_free
#define NULL
Definition: begin_code.h:164
SDL_bool
Definition: SDL_stdinc.h:139
SDL_TLSID SDL_TLSCreate()
Create an identifier that is globally visible to all threads but refers to data that is thread-specif...
Definition: SDL_thread.c:34
#define SDL_malloc
int SDL_SpinLock
Definition: SDL_atomic.h:89

◆ SDL_GetThreadID()

SDL_threadID SDL_GetThreadID ( SDL_Thread thread)

Get the thread identifier for the specified thread.

Equivalent to SDL_ThreadID() if the specified thread is NULL.

Definition at line 437 of file SDL_thread.c.

References SDL_ThreadID, and SDL_Thread::threadid.

438 {
440 
441  if (thread) {
442  id = thread->threadid;
443  } else {
444  id = SDL_ThreadID();
445  }
446  return id;
447 }
#define SDL_ThreadID
GLuint id
SDL_threadID threadid
Definition: SDL_thread_c.h:56
unsigned long SDL_threadID
Definition: SDL_thread.h:49

◆ SDL_GetThreadName()

const char* SDL_GetThreadName ( SDL_Thread thread)

Get the thread name, as it was specified in SDL_CreateThread(). This function returns a pointer to a UTF-8 string that names the specified thread, or NULL if it doesn't have a name. This is internal memory, not to be free()'d by the caller, and remains valid until the specified thread is cleaned up by SDL_WaitThread().

Definition at line 450 of file SDL_thread.c.

References SDL_Thread::name, and NULL.

451 {
452  if (thread) {
453  return thread->name;
454  } else {
455  return NULL;
456  }
457 }
char * name
Definition: SDL_thread_c.h:61
#define NULL
Definition: begin_code.h:164

◆ SDL_RunThread()

void SDL_RunThread ( void data)

Definition at line 265 of file SDL_thread.c.

References thread_args::data, thread_args::func, thread_args::info, SDL_AtomicCAS, SDL_free, SDL_SemPost, SDL_SYS_SetupThread(), SDL_THREAD_STATE_ALIVE, SDL_THREAD_STATE_CLEANED, SDL_THREAD_STATE_DETACHED, SDL_THREAD_STATE_ZOMBIE, SDL_ThreadID, SDL_TLSCleanup(), SDLCALL, SDL_TLSEntry::thread, and thread_args::wait.

Referenced by RunThread().

266 {
267  thread_args *args = (thread_args *) data;
268  int (SDLCALL * userfunc) (void *) = args->func;
269  void *userdata = args->data;
270  SDL_Thread *thread = args->info;
271  int *statusloc = &thread->status;
272 
273  /* Perform any system-dependent setup - this function may not fail */
274  SDL_SYS_SetupThread(thread->name);
275 
276  /* Get the thread id */
277  thread->threadid = SDL_ThreadID();
278 
279  /* Wake up the parent thread */
280  SDL_SemPost(args->wait);
281 
282  /* Run the function */
283  *statusloc = userfunc(userdata);
284 
285  /* Clean up thread-local storage */
286  SDL_TLSCleanup();
287 
288  /* Mark us as ready to be joined (or detached) */
290  /* Clean up if something already detached us. */
292  if (thread->name) {
293  SDL_free(thread->name);
294  }
295  SDL_free(thread);
296  }
297  }
298 }
#define SDL_ThreadID
#define SDL_AtomicCAS
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
#define SDL_SemPost
#define SDL_free
static void SDL_TLSCleanup()
Definition: SDL_thread.c:87
int(* func)(void *)
Definition: SDL_thread.c:258
SDL_Thread * info
Definition: SDL_thread.c:260
SDL_sem * wait
Definition: SDL_thread.c:261
void SDL_SYS_SetupThread(const char *name)
Definition: SDL_systhread.c:42
void * data
Definition: SDL_thread.c:259
#define SDLCALL
Definition: SDL_internal.h:45

◆ SDL_SetThreadPriority()

int SDL_SetThreadPriority ( SDL_ThreadPriority  priority)

Set the priority for the current thread

Definition at line 460 of file SDL_thread.c.

References SDL_SYS_SetThreadPriority().

461 {
462  return SDL_SYS_SetThreadPriority(priority);
463 }
int SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority)
Definition: SDL_systhread.c:54

◆ SDL_TLSCleanup()

static void SDL_TLSCleanup ( )
static

Definition at line 87 of file SDL_thread.c.

References SDL_TLSData::array, SDL_TLSData::data, SDL_TLSData::destructor, i, SDL_TLSData::limit, NULL, SDL_free, SDL_SYS_GetTLSData(), and SDL_SYS_SetTLSData().

Referenced by SDL_RunThread().

88 {
89  SDL_TLSData *storage;
90 
91  storage = SDL_SYS_GetTLSData();
92  if (storage) {
93  unsigned int i;
94  for (i = 0; i < storage->limit; ++i) {
95  if (storage->array[i].destructor) {
96  storage->array[i].destructor(storage->array[i].data);
97  }
98  }
100  SDL_free(storage);
101  }
102 }
struct SDL_TLSData::@33 array[1]
void * data
Definition: SDL_thread_c.h:73
unsigned int limit
Definition: SDL_thread_c.h:71
int SDL_SYS_SetTLSData(SDL_TLSData *data)
Definition: SDL_systls.c:33
SDL_TLSData * SDL_SYS_GetTLSData(void)
Definition: SDL_systls.c:27
#define SDL_free
void(* destructor)(void *)
Definition: SDL_thread_c.h:74
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:50
#define NULL
Definition: begin_code.h:164

◆ SDL_TLSCreate()

SDL_TLSID SDL_TLSCreate ( void  )

Create an identifier that is globally visible to all threads but refers to data that is thread-specific.

Returns
The newly created thread local storage identifier, or 0 on error
static SDL_SpinLock tls_lock;
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, 0);
}
void *GetMyThreadData(void)
{
return SDL_TLSGet(thread_local_storage);
}
See also
SDL_TLSGet()
SDL_TLSSet()

Definition at line 34 of file SDL_thread.c.

References SDL_AtomicIncRef.

Referenced by SDL_GetErrBuf().

35 {
36  static SDL_atomic_t SDL_tls_id;
37  return SDL_AtomicIncRef(&SDL_tls_id)+1;
38 }
A type representing an atomic integer value. It is a struct so people don&#39;t accidentally use numeric ...
Definition: SDL_atomic.h:198
#define SDL_AtomicIncRef(a)
Increment an atomic variable used as a reference count.
Definition: SDL_atomic.h:234

◆ SDL_TLSGet()

void* SDL_TLSGet ( SDL_TLSID  id)

Get the value associated with a thread local storage ID for the current thread.

Parameters
idThe thread local storage ID
Returns
The value associated with the ID for the current thread, or NULL if no value has been set.
See also
SDL_TLSCreate()
SDL_TLSSet()

Definition at line 41 of file SDL_thread.c.

References SDL_TLSData::array, SDL_TLSData::data, SDL_TLSData::limit, NULL, and SDL_SYS_GetTLSData().

Referenced by SDL_GetErrBuf().

42 {
43  SDL_TLSData *storage;
44 
45  storage = SDL_SYS_GetTLSData();
46  if (!storage || id == 0 || id > storage->limit) {
47  return NULL;
48  }
49  return storage->array[id-1].data;
50 }
struct SDL_TLSData::@33 array[1]
void * data
Definition: SDL_thread_c.h:73
unsigned int limit
Definition: SDL_thread_c.h:71
SDL_TLSData * SDL_SYS_GetTLSData(void)
Definition: SDL_systls.c:27
#define NULL
Definition: begin_code.h:164

◆ SDL_TLSSet()

int SDL_TLSSet ( SDL_TLSID  id,
const void value,
void(*)(void *)  destructor 
)

Set the value associated with a thread local storage ID for the current thread.

Parameters
idThe thread local storage ID
valueThe value to associate with the ID for the current thread
destructorA function called when the thread exits, to free the value.
Returns
0 on success, -1 on error
See also
SDL_TLSCreate()
SDL_TLSGet()

Definition at line 53 of file SDL_thread.c.

References SDL_TLSData::array, SDL_TLSData::data, SDL_TLSData::destructor, i, SDL_TLSData::limit, NULL, SDL_const_cast, SDL_InvalidParamError, SDL_OutOfMemory, SDL_realloc, SDL_SYS_GetTLSData(), SDL_SYS_SetTLSData(), and TLS_ALLOC_CHUNKSIZE.

Referenced by SDL_GetErrBuf().

54 {
55  SDL_TLSData *storage;
56 
57  if (id == 0) {
58  return SDL_InvalidParamError("id");
59  }
60 
61  storage = SDL_SYS_GetTLSData();
62  if (!storage || (id > storage->limit)) {
63  unsigned int i, oldlimit, newlimit;
64 
65  oldlimit = storage ? storage->limit : 0;
66  newlimit = (id + TLS_ALLOC_CHUNKSIZE);
67  storage = (SDL_TLSData *)SDL_realloc(storage, sizeof(*storage)+(newlimit-1)*sizeof(storage->array[0]));
68  if (!storage) {
69  return SDL_OutOfMemory();
70  }
71  storage->limit = newlimit;
72  for (i = oldlimit; i < newlimit; ++i) {
73  storage->array[i].data = NULL;
74  storage->array[i].destructor = NULL;
75  }
76  if (SDL_SYS_SetTLSData(storage) != 0) {
77  return -1;
78  }
79  }
80 
81  storage->array[id-1].data = SDL_const_cast(void*, value);
82  storage->array[id-1].destructor = destructor;
83  return 0;
84 }
#define SDL_const_cast(type, expression)
Definition: SDL_stdinc.h:117
struct SDL_TLSData::@33 array[1]
#define TLS_ALLOC_CHUNKSIZE
Definition: SDL_thread_c.h:79
void * data
Definition: SDL_thread_c.h:73
unsigned int limit
Definition: SDL_thread_c.h:71
int SDL_SYS_SetTLSData(SDL_TLSData *data)
Definition: SDL_systls.c:33
#define SDL_InvalidParamError(param)
Definition: SDL_error.h:54
#define SDL_realloc
SDL_TLSData * SDL_SYS_GetTLSData(void)
Definition: SDL_systls.c:27
void(* destructor)(void *)
Definition: SDL_thread_c.h:74
GLsizei const GLfloat * value
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:50
#define NULL
Definition: begin_code.h:164
#define SDL_OutOfMemory()
Definition: SDL_error.h:52

◆ SDL_WaitThread()

void SDL_WaitThread ( SDL_Thread thread,
int *  status 
)

Wait for a thread to finish. Threads that haven't been detached will remain (as a "zombie") until this function cleans them up. Not doing so is a resource leak.

Once a thread has been cleaned up through this function, the SDL_Thread that references it becomes invalid and should not be referenced again. As such, only one thread may call SDL_WaitThread() on another.

The return code for the thread function is placed in the area pointed to by status, if status is not NULL.

You may not wait on a thread that has been used in a call to SDL_DetachThread(). Use either that function or this one, but not both, or behavior is undefined.

It is safe to pass NULL to this function; it is a no-op.

Definition at line 466 of file SDL_thread.c.

References SDL_Thread::name, SDL_free, SDL_SYS_WaitThread(), and SDL_Thread::status.

Referenced by SDL_DetachThread().

467 {
468  if (thread) {
469  SDL_SYS_WaitThread(thread);
470  if (status) {
471  *status = thread->status;
472  }
473  if (thread->name) {
474  SDL_free(thread->name);
475  }
476  SDL_free(thread);
477  }
478 }
char * name
Definition: SDL_thread_c.h:61
void SDL_SYS_WaitThread(SDL_Thread *thread)
Definition: SDL_systhread.c:60
#define SDL_free

Variable Documentation

◆ SDL_generic_TLS

SDL_TLSEntry* SDL_generic_TLS
static

Definition at line 120 of file SDL_thread.c.

Referenced by SDL_Generic_SetTLSData().

◆ SDL_generic_TLS_mutex

SDL_mutex* SDL_generic_TLS_mutex
static

Definition at line 119 of file SDL_thread.c.