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_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 ()
 
int SDL_Generic_SetTLSData (SDL_TLSData *storage)
 
SDL_errorSDL_GetErrBuf (void)
 
void SDL_RunThread (void *data)
 
SDL_ThreadSDL_CreateThread (int(*fn)(void *), const char *name, 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

#define SDL_CreateThread   SDL_CreateThread_REAL

Definition at line 303 of file SDL_thread.c.

Function Documentation

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

Definition at line 314 of file SDL_thread.c.

References thread_args::data, thread_args::func, thread_args::info, SDL_Thread::name, 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_Thread::state, SDL_Thread::status, SDL_TLSEntry::thread, and thread_args::wait.

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

435 {
436  if (!thread) {
437  return;
438  }
439 
440  /* Grab dibs if the state is alive+joinable. */
442  SDL_SYS_DetachThread(thread);
443  } else {
444  /* all other states are pretty final, see where we landed. */
445  const int thread_state = SDL_AtomicGet(&thread->state);
446  if ((thread_state == SDL_THREAD_STATE_DETACHED) || (thread_state == SDL_THREAD_STATE_CLEANED)) {
447  return; /* already detached (you shouldn't call this twice!) */
448  } else if (thread_state == SDL_THREAD_STATE_ZOMBIE) {
449  SDL_WaitThread(thread, NULL); /* already done, clean it up. */
450  } else {
451  SDL_assert(0 && "Unexpected thread state");
452  }
453  }
454 }
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:167
#define NULL
Definition: begin_code.h:143
void SDL_WaitThread(SDL_Thread *thread, int *status)
Definition: SDL_thread.c:419
#define SDL_AtomicGet
SDL_TLSData* SDL_Generic_GetTLSData ( )

Definition at line 123 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().

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_ThreadID
SDL_TLSData * storage
Definition: SDL_thread.c:114
#define SDL_LockMutex
static SDL_mutex * SDL_generic_TLS_mutex
Definition: SDL_thread.c:118
#define SDL_AtomicLock
#define SDL_MemoryBarrierRelease()
Definition: SDL_atomic.h:180
#define SDL_CreateMutex
SDL_threadID thread
Definition: SDL_thread.c:113
static SDL_mutex * mutex
Definition: testlock.c:23
#define SDL_MemoryBarrierAcquire()
Definition: SDL_atomic.h:181
struct SDL_TLSEntry * next
Definition: SDL_thread.c:115
#define SDL_AtomicUnlock
Definition: SDL_thread.c:112
#define NULL
Definition: begin_code.h:143
static SDL_TLSEntry * SDL_generic_TLS
Definition: SDL_thread.c:119
#define SDL_UnlockMutex
int SDL_SpinLock
Definition: SDL_atomic.h:89
unsigned long SDL_threadID
Definition: SDL_thread.h:49
int SDL_Generic_SetTLSData ( SDL_TLSData storage)

Definition at line 162 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().

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_ThreadID
SDL_TLSData * storage
Definition: SDL_thread.c:114
#define SDL_LockMutex
static SDL_mutex * SDL_generic_TLS_mutex
Definition: SDL_thread.c:118
SDL_threadID thread
Definition: SDL_thread.c:113
struct SDL_TLSEntry * next
Definition: SDL_thread.c:115
void SDL_free(void *mem)
Definition: SDL_thread.c:112
#define NULL
Definition: begin_code.h:143
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
static SDL_TLSEntry * SDL_generic_TLS
Definition: SDL_thread.c:119
#define SDL_UnlockMutex
#define SDL_malloc
unsigned long SDL_threadID
Definition: SDL_thread.h:49
SDL_error* SDL_GetErrBuf ( void  )

Definition at line 205 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().

206 {
207  static SDL_SpinLock tls_lock;
208  static SDL_bool tls_being_created;
209  static SDL_TLSID tls_errbuf;
210  static SDL_error SDL_global_errbuf;
211  const SDL_error *ALLOCATION_IN_PROGRESS = (SDL_error *)-1;
212  SDL_error *errbuf;
213 
214  /* tls_being_created is there simply to prevent recursion if SDL_TLSCreate() fails.
215  It also means it's possible for another thread to also use SDL_global_errbuf,
216  but that's very unlikely and hopefully won't cause issues.
217  */
218  if (!tls_errbuf && !tls_being_created) {
219  SDL_AtomicLock(&tls_lock);
220  if (!tls_errbuf) {
221  SDL_TLSID slot;
222  tls_being_created = SDL_TRUE;
223  slot = SDL_TLSCreate();
224  tls_being_created = SDL_FALSE;
226  tls_errbuf = slot;
227  }
228  SDL_AtomicUnlock(&tls_lock);
229  }
230  if (!tls_errbuf) {
231  return &SDL_global_errbuf;
232  }
233 
235  errbuf = (SDL_error *)SDL_TLSGet(tls_errbuf);
236  if (errbuf == ALLOCATION_IN_PROGRESS) {
237  return &SDL_global_errbuf;
238  }
239  if (!errbuf) {
240  /* Mark that we're in the middle of allocating our buffer */
241  SDL_TLSSet(tls_errbuf, ALLOCATION_IN_PROGRESS, NULL);
242  errbuf = (SDL_error *)SDL_malloc(sizeof(*errbuf));
243  if (!errbuf) {
244  SDL_TLSSet(tls_errbuf, NULL, NULL);
245  return &SDL_global_errbuf;
246  }
247  SDL_zerop(errbuf);
248  SDL_TLSSet(tls_errbuf, errbuf, SDL_free);
249  }
250  return errbuf;
251 }
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
#define SDL_AtomicLock
#define SDL_MemoryBarrierRelease()
Definition: SDL_atomic.h:180
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
#define SDL_zerop(x)
Definition: SDL_stdinc.h:356
#define SDL_MemoryBarrierAcquire()
Definition: SDL_atomic.h:181
unsigned int SDL_TLSID
Definition: SDL_thread.h:52
#define SDL_AtomicUnlock
SDL_bool
Definition: SDL_stdinc.h:126
void SDL_free(void *mem)
#define NULL
Definition: begin_code.h:143
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
#define SDL_malloc
int SDL_SpinLock
Definition: SDL_atomic.h:89
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 390 of file SDL_thread.c.

References SDL_ThreadID, and SDL_Thread::threadid.

391 {
393 
394  if (thread) {
395  id = thread->threadid;
396  } else {
397  id = SDL_ThreadID();
398  }
399  return id;
400 }
#define SDL_ThreadID
GLuint id
SDL_threadID threadid
Definition: SDL_thread_c.h:56
unsigned long SDL_threadID
Definition: SDL_thread.h:49
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 403 of file SDL_thread.c.

References SDL_Thread::name, and NULL.

404 {
405  if (thread) {
406  return thread->name;
407  } else {
408  return NULL;
409  }
410 }
char * name
Definition: SDL_thread_c.h:61
#define NULL
Definition: begin_code.h:143
void SDL_RunThread ( void data)

Definition at line 264 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().

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

Set the priority for the current thread

Definition at line 413 of file SDL_thread.c.

References SDL_SYS_SetThreadPriority().

414 {
415  return SDL_SYS_SetThreadPriority(priority);
416 }
int SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority)
Definition: SDL_systhread.c:54
static void SDL_TLSCleanup ( )
static

Definition at line 86 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().

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 }
void * data
Definition: SDL_thread_c.h:72
unsigned int limit
Definition: SDL_thread_c.h:70
int SDL_SYS_SetTLSData(SDL_TLSData *data)
Definition: SDL_systls.c:33
SDL_TLSData * SDL_SYS_GetTLSData()
Definition: SDL_systls.c:27
void SDL_free(void *mem)
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:42
#define NULL
Definition: begin_code.h:143
struct SDL_TLSData::@27 array[1]
void(* destructor)(void *)
Definition: SDL_thread_c.h:73
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
1 static SDL_SpinLock tls_lock;
2 static SDL_TLSID thread_local_storage;
3 
4 void SetMyThreadData(void *value)
5 {
6  if (!thread_local_storage) {
7  SDL_AtomicLock(&tls_lock);
8  if (!thread_local_storage) {
9  thread_local_storage = SDL_TLSCreate();
10  }
11  SDL_AtomicUnlock(&tls_lock);
12  }
13  SDL_TLSSet(thread_local_storage, value, 0);
14 }
15 
16 void *GetMyThreadData(void)
17 {
18  return SDL_TLSGet(thread_local_storage);
19 }
See also
SDL_TLSGet()
SDL_TLSSet()

Definition at line 33 of file SDL_thread.c.

References SDL_AtomicIncRef.

Referenced by SDL_GetErrBuf().

34 {
35  static SDL_atomic_t SDL_tls_id;
36  return SDL_AtomicIncRef(&SDL_tls_id)+1;
37 }
A type representing an atomic integer value. It is a struct so people don&#39;t accidentally use numeric ...
Definition: SDL_atomic.h:189
#define SDL_AtomicIncRef(a)
Increment an atomic variable used as a reference count.
Definition: SDL_atomic.h:225
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.

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

Referenced by SDL_GetErrBuf().

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 }
void * data
Definition: SDL_thread_c.h:72
unsigned int limit
Definition: SDL_thread_c.h:70
SDL_TLSData * SDL_SYS_GetTLSData()
Definition: SDL_systls.c:27
#define NULL
Definition: begin_code.h:143
struct SDL_TLSData::@27 array[1]
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.

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

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_const_cast(type, expression)
Definition: SDL_stdinc.h:110
#define TLS_ALLOC_CHUNKSIZE
Definition: SDL_thread_c.h:78
void * data
Definition: SDL_thread_c.h:72
unsigned int limit
Definition: SDL_thread_c.h:70
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()
Definition: SDL_systls.c:27
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:42
#define NULL
Definition: begin_code.h:143
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
struct SDL_TLSData::@27 array[1]
void(* destructor)(void *)
Definition: SDL_thread_c.h:73
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 419 of file SDL_thread.c.

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

Referenced by SDL_DetachThread().

420 {
421  if (thread) {
422  SDL_SYS_WaitThread(thread);
423  if (status) {
424  *status = thread->status;
425  }
426  if (thread->name) {
427  SDL_free(thread->name);
428  }
429  SDL_free(thread);
430  }
431 }
char * name
Definition: SDL_thread_c.h:61
void SDL_SYS_WaitThread(SDL_Thread *thread)
Definition: SDL_systhread.c:60
void SDL_free(void *mem)

Variable Documentation

SDL_TLSEntry* SDL_generic_TLS
static

Definition at line 119 of file SDL_thread.c.

Referenced by SDL_Generic_SetTLSData().

SDL_mutex* SDL_generic_TLS_mutex
static

Definition at line 118 of file SDL_thread.c.