SDL  2.0
SDL_thread.c File Reference
#include "../SDL_internal.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
 

Macros

#define SDL_CreateThread   SDL_CreateThread_REAL
 
#define SDL_CreateThreadWithStackSize   SDL_CreateThreadWithStackSize_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 (SDL_Thread *thread)
 
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 297 of file SDL_thread.c.

◆ SDL_CreateThreadWithStackSize

#define SDL_CreateThreadWithStackSize   SDL_CreateThreadWithStackSize_REAL

Definition at line 298 of file SDL_thread.c.

Function Documentation

◆ SDL_CreateThread()

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

Definition at line 364 of file SDL_thread.c.

367 {
368  /* !!! FIXME: in 2.1, just make stackhint part of the usual API. */
369  const char *stackhint = SDL_GetHint(SDL_HINT_THREAD_STACK_SIZE);
370  size_t stacksize = 0;
371 
372  /* If the SDL_HINT_THREAD_STACK_SIZE exists, use it */
373  if (stackhint != NULL) {
374  char *endp = NULL;
375  const Sint64 hintval = SDL_strtoll(stackhint, &endp, 10);
376  if ((*stackhint != '\0') && (*endp == '\0')) { /* a valid number? */
377  if (hintval > 0) { /* reject bogus values. */
378  stacksize = (size_t) hintval;
379  }
380  }
381  }
382 
383 #ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
384  return SDL_CreateThreadWithStackSize(fn, name, stacksize, data, pfnBeginThread, pfnEndThread);
385 #else
386  return SDL_CreateThreadWithStackSize(fn, name, stacksize, data);
387 #endif
388 }
unsigned int size_t
#define SDL_strtoll
#define SDL_GetHint
#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:798
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
GLuint const GLchar * name
int64_t Sint64
Definition: SDL_stdinc.h:216
#define SDL_CreateThreadWithStackSize
Definition: SDL_thread.c:298
#define NULL
Definition: begin_code.h:163

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

◆ SDL_CreateThreadInternal()

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

Definition at line 391 of file SDL_thread.c.

392  {
393 #ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
394  return SDL_CreateThreadWithStackSize(fn, name, stacksize, data, NULL, NULL);
395 #else
396  return SDL_CreateThreadWithStackSize(fn, name, stacksize, data);
397 #endif
398 }

References NULL, and SDL_CreateThreadWithStackSize.

Referenced by open_audio_device(), and SDL_TimerInit().

◆ SDL_CreateThreadWithStackSize()

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

Definition at line 309 of file SDL_thread.c.

312 {
313  SDL_Thread *thread;
314  int ret;
315 
316  /* Allocate memory for the thread info structure */
317  thread = (SDL_Thread *) SDL_calloc(1, sizeof(*thread));
318  if (thread == NULL) {
319  SDL_OutOfMemory();
320  return NULL;
321  }
322  thread->status = -1;
324 
325  /* Set up the arguments for the thread */
326  if (name != NULL) {
327  thread->name = SDL_strdup(name);
328  if (thread->name == NULL) {
329  SDL_OutOfMemory();
330  SDL_free(thread);
331  return NULL;
332  }
333  }
334 
335  thread->userfunc = fn;
336  thread->userdata = data;
337  thread->stacksize = stacksize;
338 
339  /* Create the thread and go! */
340 #ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
341  ret = SDL_SYS_CreateThread(thread, pfnBeginThread, pfnEndThread);
342 #else
343  ret = SDL_SYS_CreateThread(thread);
344 #endif
345  if (ret < 0) {
346  /* Oops, failed. Gotta free everything */
347  SDL_free(thread->name);
348  SDL_free(thread);
349  thread = NULL;
350  }
351 
352  /* Everything is running now */
353  return thread;
354 }
#define SDL_AtomicSet
#define SDL_free
#define SDL_strdup
#define SDL_calloc
#define SDL_OutOfMemory()
Definition: SDL_error.h:88
@ SDL_THREAD_STATE_ALIVE
Definition: SDL_thread_c.h:49
int SDL_SYS_CreateThread(SDL_Thread *thread)
Definition: SDL_systhread.c:35
void * userdata
Definition: SDL_thread_c.h:66
char * name
Definition: SDL_thread_c.h:63
size_t stacksize
Definition: SDL_thread_c.h:64
int(* userfunc)(void *)
Definition: SDL_thread_c.h:65
SDL_atomic_t state
Definition: SDL_thread_c.h:61

References NULL, SDL_AtomicSet, SDL_calloc, SDL_free, SDL_OutOfMemory, SDL_strdup, SDL_SYS_CreateThread(), SDL_THREAD_STATE_ALIVE, and SDL_TLSEntry::thread.

◆ 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 445 of file SDL_thread.c.

446 {
447  if (!thread) {
448  return;
449  }
450 
451  /* Grab dibs if the state is alive+joinable. */
453  SDL_SYS_DetachThread(thread);
454  } else {
455  /* all other states are pretty final, see where we landed. */
456  const int thread_state = SDL_AtomicGet(&thread->state);
457  if ((thread_state == SDL_THREAD_STATE_DETACHED) || (thread_state == SDL_THREAD_STATE_CLEANED)) {
458  return; /* already detached (you shouldn't call this twice!) */
459  } else if (thread_state == SDL_THREAD_STATE_ZOMBIE) {
460  SDL_WaitThread(thread, NULL); /* already done, clean it up. */
461  } else {
462  SDL_assert(0 && "Unexpected thread state");
463  }
464  }
465 }
#define SDL_assert(condition)
Definition: SDL_assert.h:171
#define SDL_AtomicCAS
#define SDL_AtomicGet
void SDL_WaitThread(SDL_Thread *thread, int *status)
Definition: SDL_thread.c:430
@ SDL_THREAD_STATE_ZOMBIE
Definition: SDL_thread_c.h:51
@ SDL_THREAD_STATE_CLEANED
Definition: SDL_thread_c.h:52
@ SDL_THREAD_STATE_DETACHED
Definition: SDL_thread_c.h:50
void SDL_SYS_DetachThread(SDL_Thread *thread)
Definition: SDL_systhread.c:66

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_TLSEntry::thread.

◆ SDL_Generic_GetTLSData()

SDL_TLSData* SDL_Generic_GetTLSData ( void  )

Definition at line 123 of file SDL_thread.c.

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

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

Referenced by SDL_SYS_GetTLSData().

◆ SDL_Generic_SetTLSData()

int SDL_Generic_SetTLSData ( SDL_TLSData storage)

Definition at line 162 of file SDL_thread.c.

163 {
164  SDL_threadID thread = SDL_ThreadID();
165  SDL_TLSEntry *prev, *entry;
166 
167  /* SDL_Generic_GetTLSData() is always called first, so we can assume SDL_generic_TLS_mutex */
169  prev = NULL;
170  for (entry = SDL_generic_TLS; entry; entry = entry->next) {
171  if (entry->thread == thread) {
172  if (storage) {
173  entry->storage = storage;
174  } else {
175  if (prev) {
176  prev->next = entry->next;
177  } else {
178  SDL_generic_TLS = entry->next;
179  }
180  SDL_free(entry);
181  }
182  break;
183  }
184  prev = entry;
185  }
186  if (!entry) {
187  entry = (SDL_TLSEntry *)SDL_malloc(sizeof(*entry));
188  if (entry) {
189  entry->thread = thread;
190  entry->storage = storage;
191  entry->next = SDL_generic_TLS;
192  SDL_generic_TLS = entry;
193  }
194  }
196 
197  if (!entry) {
198  return SDL_OutOfMemory();
199  }
200  return 0;
201 }
#define SDL_malloc

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

Referenced by SDL_SYS_SetTLSData().

◆ SDL_GetErrBuf()

SDL_error* SDL_GetErrBuf ( void  )

Definition at line 205 of file SDL_thread.c.

206 {
207 #if SDL_THREADS_DISABLED
208  /* Non-thread-safe global error variable */
209  static SDL_error SDL_global_error;
210  return &SDL_global_error;
211 #else
212  static SDL_SpinLock tls_lock;
213  static SDL_bool tls_being_created;
214  static SDL_TLSID tls_errbuf;
215  static SDL_error SDL_global_errbuf;
216  const SDL_error *ALLOCATION_IN_PROGRESS = (SDL_error *)-1;
217  SDL_error *errbuf;
218 
219  /* tls_being_created is there simply to prevent recursion if SDL_TLSCreate() fails.
220  It also means it's possible for another thread to also use SDL_global_errbuf,
221  but that's very unlikely and hopefully won't cause issues.
222  */
223  if (!tls_errbuf && !tls_being_created) {
224  SDL_AtomicLock(&tls_lock);
225  if (!tls_errbuf) {
226  SDL_TLSID slot;
227  tls_being_created = SDL_TRUE;
228  slot = SDL_TLSCreate();
229  tls_being_created = SDL_FALSE;
231  tls_errbuf = slot;
232  }
233  SDL_AtomicUnlock(&tls_lock);
234  }
235  if (!tls_errbuf) {
236  return &SDL_global_errbuf;
237  }
238 
240  errbuf = (SDL_error *)SDL_TLSGet(tls_errbuf);
241  if (errbuf == ALLOCATION_IN_PROGRESS) {
242  return &SDL_global_errbuf;
243  }
244  if (!errbuf) {
245  /* Mark that we're in the middle of allocating our buffer */
246  SDL_TLSSet(tls_errbuf, ALLOCATION_IN_PROGRESS, NULL);
247  errbuf = (SDL_error *)SDL_malloc(sizeof(*errbuf));
248  if (!errbuf) {
249  SDL_TLSSet(tls_errbuf, NULL, NULL);
250  return &SDL_global_errbuf;
251  }
252  SDL_zerop(errbuf);
253  SDL_TLSSet(tls_errbuf, errbuf, SDL_free);
254  }
255  return errbuf;
256 #endif /* SDL_THREADS_DISABLED */
257 }
SDL_bool
Definition: SDL_stdinc.h:168
@ SDL_TRUE
Definition: SDL_stdinc.h:170
@ SDL_FALSE
Definition: SDL_stdinc.h:169
#define SDL_zerop(x)
Definition: SDL_stdinc.h:427
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:33
void * SDL_TLSGet(SDL_TLSID id)
Get the value associated with a thread local storage ID for the current thread.
Definition: SDL_thread.c:40
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:52
unsigned int SDL_TLSID
Definition: SDL_thread.h:52

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_GetError(), SDL_GetErrorMsg(), and SDL_SetError().

◆ 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 401 of file SDL_thread.c.

402 {
404 
405  if (thread) {
406  id = thread->threadid;
407  } else {
408  id = SDL_ThreadID();
409  }
410  return id;
411 }
GLuint id
SDL_threadID threadid
Definition: SDL_thread_c.h:58

References SDL_ThreadID, and SDL_TLSEntry::thread.

◆ 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 414 of file SDL_thread.c.

415 {
416  if (thread) {
417  return thread->name;
418  } else {
419  return NULL;
420  }
421 }

References NULL, and SDL_TLSEntry::thread.

◆ SDL_RunThread()

void SDL_RunThread ( SDL_Thread thread)

Definition at line 261 of file SDL_thread.c.

262 {
263  void *userdata = thread->userdata;
264  int (SDLCALL * userfunc) (void *) = thread->userfunc;
265 
266  int *statusloc = &thread->status;
267 
268  /* Perform any system-dependent setup - this function may not fail */
269  SDL_SYS_SetupThread(thread->name);
270 
271  /* Get the thread id */
272  thread->threadid = SDL_ThreadID();
273 
274  /* Run the function */
275  *statusloc = userfunc(userdata);
276 
277  /* Clean up thread-local storage */
278  SDL_TLSCleanup();
279 
280  /* Mark us as ready to be joined (or detached) */
282  /* Clean up if something already detached us. */
284  if (thread->name) {
285  SDL_free(thread->name);
286  }
287  SDL_free(thread);
288  }
289  }
290 }
#define SDLCALL
Definition: SDL_internal.h:49
static void SDL_TLSCleanup()
Definition: SDL_thread.c:86
void SDL_SYS_SetupThread(const char *name)
Definition: SDL_systhread.c:42
typedef int(__stdcall *FARPROC)()

References int(), SDL_AtomicCAS, SDL_free, SDL_SYS_SetupThread(), SDL_THREAD_STATE_ALIVE, SDL_THREAD_STATE_CLEANED, SDL_THREAD_STATE_DETACHED, SDL_THREAD_STATE_ZOMBIE, SDL_ThreadID, SDL_TLSCleanup(), SDLCALL, and SDL_TLSEntry::thread.

Referenced by RunThread().

◆ SDL_SetThreadPriority()

int SDL_SetThreadPriority ( SDL_ThreadPriority  priority)

Set the priority for the current thread

Definition at line 424 of file SDL_thread.c.

425 {
426  return SDL_SYS_SetThreadPriority(priority);
427 }
int SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority)
Definition: SDL_systhread.c:54

References SDL_SYS_SetThreadPriority().

◆ SDL_TLSCleanup()

static void SDL_TLSCleanup ( )
static

Definition at line 86 of file SDL_thread.c.

87 {
88  SDL_TLSData *storage;
89 
90  storage = SDL_SYS_GetTLSData();
91  if (storage) {
92  unsigned int i;
93  for (i = 0; i < storage->limit; ++i) {
94  if (storage->array[i].destructor) {
95  storage->array[i].destructor(storage->array[i].data);
96  }
97  }
99  SDL_free(storage);
100  }
101 }
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
int SDL_SYS_SetTLSData(SDL_TLSData *data)
Definition: SDL_systls.c:33
SDL_TLSData * SDL_SYS_GetTLSData(void)
Definition: SDL_systls.c:27
struct SDL_TLSData::@46 array[1]
void * data
Definition: SDL_thread_c.h:78
unsigned int limit
Definition: SDL_thread_c.h:76
void(* destructor)(void *)
Definition: SDL_thread_c.h:79

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().

◆ 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)
{
SDL_AtomicLock(&tls_lock);
}
SDL_AtomicUnlock(&tls_lock);
}
}
void *GetMyThreadData(void)
{
}
#define SDL_TLSCreate
#define SDL_TLSSet
#define SDL_TLSGet
GLsizei const GLfloat * value
static pthread_key_t thread_local_storage
Definition: SDL_systls.c:31
See also
SDL_TLSGet()
SDL_TLSSet()

Definition at line 33 of file SDL_thread.c.

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

References SDL_AtomicIncRef.

Referenced by SDL_GetErrBuf().

◆ 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 40 of file SDL_thread.c.

41 {
42  SDL_TLSData *storage;
43 
44  storage = SDL_SYS_GetTLSData();
45  if (!storage || id == 0 || id > storage->limit) {
46  return NULL;
47  }
48  return storage->array[id-1].data;
49 }

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

Referenced by SDL_GetErrBuf().

◆ 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 52 of file SDL_thread.c.

53 {
54  SDL_TLSData *storage;
55 
56  if (id == 0) {
57  return SDL_InvalidParamError("id");
58  }
59 
60  storage = SDL_SYS_GetTLSData();
61  if (!storage || (id > storage->limit)) {
62  unsigned int i, oldlimit, newlimit;
63 
64  oldlimit = storage ? storage->limit : 0;
65  newlimit = (id + TLS_ALLOC_CHUNKSIZE);
66  storage = (SDL_TLSData *)SDL_realloc(storage, sizeof(*storage)+(newlimit-1)*sizeof(storage->array[0]));
67  if (!storage) {
68  return SDL_OutOfMemory();
69  }
70  storage->limit = newlimit;
71  for (i = oldlimit; i < newlimit; ++i) {
72  storage->array[i].data = NULL;
73  storage->array[i].destructor = NULL;
74  }
75  if (SDL_SYS_SetTLSData(storage) != 0) {
76  return -1;
77  }
78  }
79 
80  storage->array[id-1].data = SDL_const_cast(void*, value);
81  storage->array[id-1].destructor = destructor;
82  return 0;
83 }
#define SDL_realloc
#define SDL_InvalidParamError(param)
Definition: SDL_error.h:90
#define SDL_const_cast(type, expression)
Definition: SDL_stdinc.h:145
#define TLS_ALLOC_CHUNKSIZE
Definition: SDL_thread_c.h:84

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().

◆ 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 430 of file SDL_thread.c.

431 {
432  if (thread) {
433  SDL_SYS_WaitThread(thread);
434  if (status) {
435  *status = thread->status;
436  }
437  if (thread->name) {
438  SDL_free(thread->name);
439  }
440  SDL_free(thread);
441  }
442 }
void SDL_SYS_WaitThread(SDL_Thread *thread)
Definition: SDL_systhread.c:60

References SDL_free, SDL_SYS_WaitThread(), and SDL_TLSEntry::thread.

Referenced by SDL_DetachThread().

Variable Documentation

◆ SDL_generic_TLS

SDL_TLSEntry* SDL_generic_TLS
static

Definition at line 119 of file SDL_thread.c.

Referenced by SDL_Generic_GetTLSData(), and SDL_Generic_SetTLSData().

◆ SDL_generic_TLS_mutex

SDL_mutex* SDL_generic_TLS_mutex
static

Definition at line 118 of file SDL_thread.c.

Referenced by SDL_Generic_GetTLSData(), and SDL_Generic_SetTLSData().