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
 
#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 (void *data)
 
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 305 of file SDL_thread.c.

◆ SDL_CreateThreadWithStackSize

#define SDL_CreateThreadWithStackSize   SDL_CreateThreadWithStackSize_REAL

Definition at line 306 of file SDL_thread.c.

Function Documentation

◆ SDL_CreateThread()

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

Definition at line 402 of file SDL_thread.c.

405{
406 /* !!! FIXME: in 2.1, just make stackhint part of the usual API. */
407 const char *stackhint = SDL_GetHint(SDL_HINT_THREAD_STACK_SIZE);
408 size_t stacksize = 0;
409
410 /* If the SDL_HINT_THREAD_STACK_SIZE exists, use it */
411 if (stackhint != NULL) {
412 char *endp = NULL;
413 const Sint64 hintval = SDL_strtoll(stackhint, &endp, 10);
414 if ((*stackhint != '\0') && (*endp == '\0')) { /* a valid number? */
415 if (hintval > 0) { /* reject bogus values. */
416 stacksize = (size_t) hintval;
417 }
418 }
419 }
420
421#ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
422 return SDL_CreateThreadWithStackSize(fn, name, stacksize, data, pfnBeginThread, pfnEndThread);
423#else
424 return SDL_CreateThreadWithStackSize(fn, name, stacksize, data);
425#endif
426}
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:647
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:210
#define SDL_CreateThreadWithStackSize
Definition: SDL_thread.c:306
#define NULL
Definition: begin_code.h:167

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

430 {
431#ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
432 return SDL_CreateThreadWithStackSize(fn, name, stacksize, data, NULL, NULL);
433#else
434 return SDL_CreateThreadWithStackSize(fn, name, stacksize, data);
435#endif
436}

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

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

References thread_args::data, thread_args::func, thread_args::info, NULL, SDL_AtomicSet, SDL_CreateSemaphore, SDL_DestroySemaphore, SDL_free, SDL_malloc, SDL_OutOfMemory, SDL_SemWait, SDL_strdup, SDL_SYS_CreateThread(), SDL_THREAD_STATE_ALIVE, SDL_zerop, SDL_TLSEntry::thread, and thread_args::wait.

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

484{
485 if (!thread) {
486 return;
487 }
488
489 /* Grab dibs if the state is alive+joinable. */
491 SDL_SYS_DetachThread(thread);
492 } else {
493 /* all other states are pretty final, see where we landed. */
494 const int thread_state = SDL_AtomicGet(&thread->state);
495 if ((thread_state == SDL_THREAD_STATE_DETACHED) || (thread_state == SDL_THREAD_STATE_CLEANED)) {
496 return; /* already detached (you shouldn't call this twice!) */
497 } else if (thread_state == SDL_THREAD_STATE_ZOMBIE) {
498 SDL_WaitThread(thread, NULL); /* already done, clean it up. */
499 } else {
500 SDL_assert(0 && "Unexpected thread state");
501 }
502 }
503}
#define SDL_assert(condition)
Definition: SDL_assert.h:169
#define SDL_AtomicCAS
#define SDL_AtomicGet
void SDL_WaitThread(SDL_Thread *thread, int *status)
Definition: SDL_thread.c:468
@ SDL_THREAD_STATE_ZOMBIE
Definition: SDL_thread_c.h:49
@ SDL_THREAD_STATE_CLEANED
Definition: SDL_thread_c.h:50
@ SDL_THREAD_STATE_DETACHED
Definition: SDL_thread_c.h:48
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 124 of file SDL_thread.c.

125{
126 SDL_threadID thread = SDL_ThreadID();
127 SDL_TLSEntry *entry;
128 SDL_TLSData *storage = NULL;
129
130#if !SDL_THREADS_DISABLED
132 static SDL_SpinLock tls_lock;
133 SDL_AtomicLock(&tls_lock);
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_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:120
static SDL_mutex * SDL_generic_TLS_mutex
Definition: SDL_thread.c:119
unsigned long SDL_threadID
Definition: SDL_thread.h:49
Definition: SDL_thread.c:113
SDL_TLSData * storage
Definition: SDL_thread.c:115
SDL_threadID thread
Definition: SDL_thread.c:114
struct SDL_TLSEntry * next
Definition: SDL_thread.c:116
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 163 of file SDL_thread.c.

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}

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

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}
SDL_bool
Definition: SDL_stdinc.h:162
@ SDL_TRUE
Definition: SDL_stdinc.h:164
@ SDL_FALSE
Definition: SDL_stdinc.h:163
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
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
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
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_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 439 of file SDL_thread.c.

440{
442
443 if (thread) {
444 id = thread->threadid;
445 } else {
446 id = SDL_ThreadID();
447 }
448 return id;
449}
GLuint id
SDL_threadID threadid
Definition: SDL_thread_c.h:56

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

453{
454 if (thread) {
455 return thread->name;
456 } else {
457 return NULL;
458 }
459}

References NULL, and SDL_TLSEntry::thread.

◆ SDL_RunThread()

void SDL_RunThread ( void data)

Definition at line 265 of file SDL_thread.c.

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 */
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_SemPost
#define SDLCALL
Definition: SDL_internal.h:49
static void SDL_TLSCleanup()
Definition: SDL_thread.c:87
void SDL_SYS_SetupThread(const char *name)
Definition: SDL_systhread.c:42

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

◆ SDL_SetThreadPriority()

int SDL_SetThreadPriority ( SDL_ThreadPriority  priority)

Set the priority for the current thread

Definition at line 462 of file SDL_thread.c.

463{
464 return SDL_SYS_SetThreadPriority(priority);
465}
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 87 of file SDL_thread.c.

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}
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
SDL_TLSData * SDL_SYS_GetTLSData(void)
Definition: SDL_systls.c:27
int SDL_SYS_SetTLSData(SDL_TLSData *data)
Definition: SDL_systls.c:33
void * data
Definition: SDL_thread_c.h:73
unsigned int limit
Definition: SDL_thread_c.h:71
void(* destructor)(void *)
Definition: SDL_thread_c.h:74
struct SDL_TLSData::@39 array[1]

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

35{
36 static SDL_atomic_t SDL_tls_id;
37 return SDL_AtomicIncRef(&SDL_tls_id)+1;
38}
#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 41 of file SDL_thread.c.

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}

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

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_realloc
#define SDL_InvalidParamError(param)
Definition: SDL_error.h:54
#define SDL_const_cast(type, expression)
Definition: SDL_stdinc.h:139
#define TLS_ALLOC_CHUNKSIZE
Definition: SDL_thread_c.h:79

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

469{
470 if (thread) {
471 SDL_SYS_WaitThread(thread);
472 if (status) {
473 *status = thread->status;
474 }
475 if (thread->name) {
476 SDL_free(thread->name);
477 }
478 SDL_free(thread);
479 }
480}
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 120 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 119 of file SDL_thread.c.

Referenced by SDL_Generic_GetTLSData(), and SDL_Generic_SetTLSData().