SDL  2.0
SDL_mutex.h File Reference
#include "SDL_stdinc.h"
#include "SDL_error.h"
#include "begin_code.h"
#include "close_code.h"
+ Include dependency graph for SDL_mutex.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define SDL_MUTEX_TIMEDOUT   1
 
#define SDL_MUTEX_MAXWAIT   (~(Uint32)0)
 

Functions

Semaphore functions
SDL_sem * SDL_CreateSemaphore (Uint32 initial_value)
 
void SDL_DestroySemaphore (SDL_sem *sem)
 
int SDL_SemWait (SDL_sem *sem)
 
int SDL_SemTryWait (SDL_sem *sem)
 
int SDL_SemWaitTimeout (SDL_sem *sem, Uint32 ms)
 
int SDL_SemPost (SDL_sem *sem)
 
Uint32 SDL_SemValue (SDL_sem *sem)
 
Condition variable functions
SDL_condSDL_CreateCond (void)
 
void SDL_DestroyCond (SDL_cond *cond)
 
int SDL_CondSignal (SDL_cond *cond)
 
int SDL_CondBroadcast (SDL_cond *cond)
 
int SDL_CondWait (SDL_cond *cond, SDL_mutex *mutex)
 
int SDL_CondWaitTimeout (SDL_cond *cond, SDL_mutex *mutex, Uint32 ms)
 

Mutex functions

#define SDL_mutexP(m)   SDL_LockMutex(m)
 
#define SDL_mutexV(m)   SDL_UnlockMutex(m)
 
SDL_mutexSDL_CreateMutex (void)
 
int SDL_LockMutex (SDL_mutex *mutex)
 
int SDL_TryLockMutex (SDL_mutex *mutex)
 
int SDL_UnlockMutex (SDL_mutex *mutex)
 
void SDL_DestroyMutex (SDL_mutex *mutex)
 

Detailed Description

Functions to provide thread synchronization primitives.

Definition in file SDL_mutex.h.

Macro Definition Documentation

◆ SDL_MUTEX_MAXWAIT

#define SDL_MUTEX_MAXWAIT   (~(Uint32)0)

This is the timeout value which corresponds to never time out.

Definition at line 49 of file SDL_mutex.h.

◆ SDL_MUTEX_TIMEDOUT

#define SDL_MUTEX_TIMEDOUT   1

Synchronization functions which can time out return this value if they time out.

Definition at line 44 of file SDL_mutex.h.

◆ SDL_mutexP

#define SDL_mutexP (   m)    SDL_LockMutex(m)

Lock the mutex.

Returns
0, or -1 on error.

Definition at line 71 of file SDL_mutex.h.

◆ SDL_mutexV

#define SDL_mutexV (   m)    SDL_UnlockMutex(m)

Unlock the mutex.

Returns
0, or -1 on error.
Warning
It is an error to unlock a mutex that has not been locked by the current thread, and doing so results in undefined behavior.

Definition at line 89 of file SDL_mutex.h.

Function Documentation

◆ SDL_CondBroadcast()

int SDL_CondBroadcast ( SDL_cond cond)

Restart all threads that are waiting on the condition variable.

Returns
0 or -1 on error.

Definition at line 106 of file SDL_syscond.c.

107 {
108  if (!cond) {
109  return SDL_SetError("Passed a NULL condition variable");
110  }
111 
112  /* If there are waiting threads not already signalled, then
113  signal the condition and wait for the thread to respond.
114  */
115  SDL_LockMutex(cond->lock);
116  if (cond->waiting > cond->signals) {
117  int i, num_waiting;
118 
119  num_waiting = (cond->waiting - cond->signals);
120  cond->signals = cond->waiting;
121  for (i = 0; i < num_waiting; ++i) {
122  SDL_SemPost(cond->wait_sem);
123  }
124  /* Now all released threads are blocked here, waiting for us.
125  Collect them all (and win fabulous prizes!) :-)
126  */
127  SDL_UnlockMutex(cond->lock);
128  for (i = 0; i < num_waiting; ++i) {
129  SDL_SemWait(cond->wait_done);
130  }
131  } else {
132  SDL_UnlockMutex(cond->lock);
133  }
134 
135  return 0;
136 }
#define SDL_SetError
#define SDL_SemPost
#define SDL_SemWait
#define SDL_LockMutex
#define SDL_UnlockMutex
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
set set set set set set set set set set set set set set set set set set set set *set set set macro pixldst cond

References cond, i, retval, SDL_LockMutex, SDL_SemPost, SDL_SemWait, SDL_SetError, and SDL_UnlockMutex.

◆ SDL_CondSignal()

int SDL_CondSignal ( SDL_cond cond)

Restart one of the threads that are waiting on the condition variable.

Returns
0 or -1 on error.

Definition at line 82 of file SDL_syscond.c.

83 {
84  if (!cond) {
85  return SDL_SetError("Passed a NULL condition variable");
86  }
87 
88  /* If there are waiting threads not already signalled, then
89  signal the condition and wait for the thread to respond.
90  */
91  SDL_LockMutex(cond->lock);
92  if (cond->waiting > cond->signals) {
93  ++cond->signals;
94  SDL_SemPost(cond->wait_sem);
95  SDL_UnlockMutex(cond->lock);
96  SDL_SemWait(cond->wait_done);
97  } else {
98  SDL_UnlockMutex(cond->lock);
99  }
100 
101  return 0;
102 }

References cond, retval, SDL_LockMutex, SDL_SemPost, SDL_SemWait, SDL_SetError, and SDL_UnlockMutex.

◆ SDL_CondWait()

int SDL_CondWait ( SDL_cond cond,
SDL_mutex mutex 
)

Wait on the condition variable, unlocking the provided mutex.

Warning
The mutex must be locked before entering this function!

The mutex is re-locked once the condition variable is signaled.

Returns
0 when it is signaled, or -1 on error.

Definition at line 215 of file SDL_syscond.c.

216 {
218 }
#define SDL_MUTEX_MAXWAIT
Definition: SDL_mutex.h:49
int SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms)
Definition: SDL_syscond.c:160
static SDL_mutex * mutex
Definition: testlock.c:23

References cond, SDL_mutex::id, mutex, SDL_CondWaitTimeout(), SDL_MUTEX_MAXWAIT, and SDL_SetError.

◆ SDL_CondWaitTimeout()

int SDL_CondWaitTimeout ( SDL_cond cond,
SDL_mutex mutex,
Uint32  ms 
)

Waits for at most ms milliseconds, and returns 0 if the condition variable is signaled, SDL_MUTEX_TIMEDOUT if the condition is not signaled in the allotted time, and -1 on error.

Warning
On some platforms this function is implemented by looping with a delay of 1 ms, and so should be avoided if possible.

Definition at line 160 of file SDL_syscond.c.

161 {
162  int retval;
163 
164  if (!cond) {
165  return SDL_SetError("Passed a NULL condition variable");
166  }
167 
168  /* Obtain the protection mutex, and increment the number of waiters.
169  This allows the signal mechanism to only perform a signal if there
170  are waiting threads.
171  */
172  SDL_LockMutex(cond->lock);
173  ++cond->waiting;
174  SDL_UnlockMutex(cond->lock);
175 
176  /* Unlock the mutex, as is required by condition variable semantics */
178 
179  /* Wait for a signal */
180  if (ms == SDL_MUTEX_MAXWAIT) {
181  retval = SDL_SemWait(cond->wait_sem);
182  } else {
183  retval = SDL_SemWaitTimeout(cond->wait_sem, ms);
184  }
185 
186  /* Let the signaler know we have completed the wait, otherwise
187  the signaler can race ahead and get the condition semaphore
188  if we are stopped between the mutex unlock and semaphore wait,
189  giving a deadlock. See the following URL for details:
190  http://web.archive.org/web/20010914175514/http://www-classic.be.com/aboutbe/benewsletter/volume_III/Issue40.html#Workshop
191  */
192  SDL_LockMutex(cond->lock);
193  if (cond->signals > 0) {
194  /* If we timed out, we need to eat a condition signal */
195  if (retval > 0) {
196  SDL_SemWait(cond->wait_sem);
197  }
198  /* We always notify the signal thread that we are done */
199  SDL_SemPost(cond->wait_done);
200 
201  /* Signal handshake complete */
202  --cond->signals;
203  }
204  --cond->waiting;
205  SDL_UnlockMutex(cond->lock);
206 
207  /* Lock the mutex, as is required by condition variable semantics */
209 
210  return retval;
211 }
#define SDL_SemWaitTimeout
SDL_bool retval

References cond, SDL_mutex::cpp_mutex, SDL_mutex::id, mutex, NULL, retval, SDL_LockMutex, SDL_MUTEX_MAXWAIT, SDL_MUTEX_TIMEDOUT, SDL_SemPost, SDL_SemWait, SDL_SemWaitTimeout, SDL_SetError, and SDL_UnlockMutex.

Referenced by SDL_CondWait().

◆ SDL_CreateCond()

SDL_cond* SDL_CreateCond ( void  )

Create a condition variable.

Typical use of condition variables:

Thread A: SDL_LockMutex(lock); while ( ! condition ) { SDL_CondWait(cond, lock); } SDL_UnlockMutex(lock);

Thread B: SDL_LockMutex(lock); ... condition = true; ... SDL_CondSignal(cond); SDL_UnlockMutex(lock);

There is some discussion whether to signal the condition variable with the mutex locked or not. There is some potential performance benefit to unlocking first on some platforms, but there are some potential race conditions depending on how your code is structured.

In general it's safer to signal the condition variable while the mutex is locked.

Definition at line 42 of file SDL_syscond.c.

43 {
44  SDL_cond *cond;
45 
46  cond = (SDL_cond *) SDL_malloc(sizeof(SDL_cond));
47  if (cond) {
48  cond->lock = SDL_CreateMutex();
49  cond->wait_sem = SDL_CreateSemaphore(0);
50  cond->wait_done = SDL_CreateSemaphore(0);
51  cond->waiting = cond->signals = 0;
52  if (!cond->lock || !cond->wait_sem || !cond->wait_done) {
54  cond = NULL;
55  }
56  } else {
58  }
59  return (cond);
60 }
#define SDL_malloc
#define SDL_CreateMutex
#define SDL_CreateSemaphore
#define SDL_OutOfMemory()
Definition: SDL_error.h:88
#define NULL
Definition: begin_code.h:163
void SDL_DestroyCond(SDL_cond *cond)
Definition: SDL_syscond.c:64

References cond, NULL, SDL_CreateMutex, SDL_CreateSemaphore, SDL_DestroyCond(), SDL_free, SDL_malloc, SDL_OutOfMemory, and SDL_SetError.

◆ SDL_CreateMutex()

SDL_mutex* SDL_CreateMutex ( void  )

Create a mutex, initialized unlocked.

Definition at line 38 of file SDL_sysmutex.c.

39 {
41 
42  /* Allocate mutex memory */
43  mutex = (SDL_mutex *) SDL_malloc(sizeof(*mutex));
44  if (mutex) {
45  /* Create the mutex semaphore, with initial value 1 */
47  mutex->recursive = 0;
48  mutex->owner = 0;
49  if (!mutex->sem) {
50  SDL_free(mutex);
51  mutex = NULL;
52  }
53  } else {
55  }
56  return mutex;
57 }
#define SDL_free
SDL_threadID owner
Definition: SDL_sysmutex.c:32
int recursive
Definition: SDL_sysmutex.c:31
SDL_sem * sem
Definition: SDL_sysmutex.c:33

References SDL_mutex::id, mutex, NULL, SDL_mutex::owner, SDL_mutex::recursive, SDL_calloc, SDL_CreateSemaphore, SDL_free, SDL_malloc, SDL_OutOfMemory, SDL_SetError, and SDL_mutex::sem.

◆ SDL_CreateSemaphore()

SDL_sem* SDL_CreateSemaphore ( Uint32  initial_value)

Create a semaphore, initialized with value, returns NULL on failure.

Definition at line 85 of file SDL_syssem.c.

86 {
87  SDL_sem *sem;
88 
89  sem = (SDL_sem *) SDL_malloc(sizeof(*sem));
90  if (!sem) {
92  return NULL;
93  }
94  sem->count = initial_value;
95  sem->waiters_count = 0;
96 
97  sem->count_lock = SDL_CreateMutex();
98  sem->count_nonzero = SDL_CreateCond();
99  if (!sem->count_lock || !sem->count_nonzero) {
101  return NULL;
102  }
103 
104  return sem;
105 }
#define SDL_CreateCond
void SDL_DestroySemaphore(SDL_sem *sem)
Definition: SDL_syssem.c:111
static SDL_sem * sem
Definition: testsem.c:23

References NULL, SDL_CreateCond, SDL_CreateMutex, SDL_DestroySemaphore(), SDL_free, SDL_malloc, SDL_OutOfMemory, SDL_SetError, and sem.

◆ SDL_DestroyCond()

void SDL_DestroyCond ( SDL_cond cond)

Destroy a condition variable.

Definition at line 64 of file SDL_syscond.c.

65 {
66  if (cond) {
67  if (cond->wait_sem) {
68  SDL_DestroySemaphore(cond->wait_sem);
69  }
70  if (cond->wait_done) {
71  SDL_DestroySemaphore(cond->wait_done);
72  }
73  if (cond->lock) {
74  SDL_DestroyMutex(cond->lock);
75  }
76  SDL_free(cond);
77  }
78 }
#define SDL_DestroySemaphore
#define SDL_DestroyMutex

References cond, SDL_DestroyMutex, SDL_DestroySemaphore, and SDL_free.

Referenced by SDL_CreateCond().

◆ SDL_DestroyMutex()

void SDL_DestroyMutex ( SDL_mutex mutex)

Destroy a mutex.

Definition at line 61 of file SDL_sysmutex.c.

62 {
63  if (mutex) {
64  if (mutex->sem) {
66  }
67  SDL_free(mutex);
68  }
69 }

References SDL_mutex::id, mutex, SDL_DestroySemaphore, SDL_free, and SDL_mutex::sem.

◆ SDL_DestroySemaphore()

void SDL_DestroySemaphore ( SDL_sem *  sem)

Destroy a semaphore.

Definition at line 111 of file SDL_syssem.c.

112 {
113  if (sem) {
114  sem->count = 0xFFFFFFFF;
115  while (sem->waiters_count > 0) {
116  SDL_CondSignal(sem->count_nonzero);
117  SDL_Delay(10);
118  }
119  SDL_DestroyCond(sem->count_nonzero);
120  if (sem->count_lock) {
121  SDL_LockMutex(sem->count_lock);
122  SDL_UnlockMutex(sem->count_lock);
123  SDL_DestroyMutex(sem->count_lock);
124  }
125  SDL_free(sem);
126  }
127 }
#define SDL_CondSignal
#define SDL_Delay
#define SDL_DestroyCond

References SDL_CondSignal, SDL_Delay, SDL_DestroyCond, SDL_DestroyMutex, SDL_free, SDL_LockMutex, SDL_UnlockMutex, and sem.

Referenced by SDL_CreateSemaphore().

◆ SDL_LockMutex()

int SDL_LockMutex ( SDL_mutex mutex)

Definition at line 73 of file SDL_sysmutex.c.

74 {
75 #if SDL_THREADS_DISABLED
76  return 0;
77 #else
78  SDL_threadID this_thread;
79 
80  if (mutex == NULL) {
81  return SDL_SetError("Passed a NULL mutex");
82  }
83 
84  this_thread = SDL_ThreadID();
85  if (mutex->owner == this_thread) {
86  ++mutex->recursive;
87  } else {
88  /* The order of operations is important.
89  We set the locking thread id after we obtain the lock
90  so unlocks from other threads will fail.
91  */
93  mutex->owner = this_thread;
94  mutex->recursive = 0;
95  }
96 
97  return 0;
98 #endif /* SDL_THREADS_DISABLED */
99 }
#define SDL_ThreadID
unsigned long SDL_threadID
Definition: SDL_thread.h:49

References SDL_mutex::id, mutex, NULL, SDL_mutex::owner, SDL_mutex::recursive, SDL_SemWait, SDL_SetError, SDL_ThreadID, and SDL_mutex::sem.

◆ SDL_SemPost()

int SDL_SemPost ( SDL_sem *  sem)

Atomically increases the semaphore's count (not blocking).

Returns
0, or -1 on error.

Definition at line 200 of file SDL_syssem.c.

201 {
202  if (!sem) {
203  return SDL_SetError("Passed a NULL semaphore");
204  }
205 
206  SDL_LockMutex(sem->count_lock);
207  if (sem->waiters_count > 0) {
208  SDL_CondSignal(sem->count_nonzero);
209  }
210  ++sem->count;
211  SDL_UnlockMutex(sem->count_lock);
212 
213  return 0;
214 }

References retval, SDL_CondSignal, SDL_LockMutex, SDL_SetError, SDL_UnlockMutex, and sem.

◆ SDL_SemTryWait()

int SDL_SemTryWait ( SDL_sem *  sem)

Non-blocking variant of SDL_SemWait().

Returns
0 if the wait succeeds, SDL_MUTEX_TIMEDOUT if the wait would block, and -1 on error.

Definition at line 130 of file SDL_syssem.c.

131 {
132  int retval;
133 
134  if (!sem) {
135  return SDL_SetError("Passed a NULL semaphore");
136  }
137 
139  SDL_LockMutex(sem->count_lock);
140  if (sem->count > 0) {
141  --sem->count;
142  retval = 0;
143  }
144  SDL_UnlockMutex(sem->count_lock);
145 
146  return retval;
147 }
#define SDL_MUTEX_TIMEDOUT
Definition: SDL_mutex.h:44

References retval, SDL_LockMutex, SDL_MUTEX_TIMEDOUT, SDL_SetError, SDL_UnlockMutex, and sem.

Referenced by SDL_SemWaitTimeout().

◆ SDL_SemValue()

Uint32 SDL_SemValue ( SDL_sem *  sem)

Returns the current count of the semaphore.

Definition at line 186 of file SDL_syssem.c.

187 {
188  Uint32 value;
189 
190  value = 0;
191  if (sem) {
192  SDL_LockMutex(sem->count_lock);
193  value = sem->count;
194  SDL_UnlockMutex(sem->count_lock);
195  }
196  return value;
197 }
GLsizei const GLfloat * value
uint32_t Uint32
Definition: SDL_stdinc.h:209

References SDL_LockMutex, SDL_UnlockMutex, and sem.

◆ SDL_SemWait()

int SDL_SemWait ( SDL_sem *  sem)

This function suspends the calling thread until the semaphore pointed to by sem has a positive count. It then atomically decreases the semaphore count.

Definition at line 180 of file SDL_syssem.c.

181 {
183 }
int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
Definition: SDL_syssem.c:150

References retval, SDL_MUTEX_MAXWAIT, SDL_SemWaitTimeout(), SDL_SetError, and sem.

Referenced by SDL_SemWaitTimeout().

◆ SDL_SemWaitTimeout()

int SDL_SemWaitTimeout ( SDL_sem *  sem,
Uint32  ms 
)

Variant of SDL_SemWait() with a timeout in milliseconds.

Returns
0 if the wait succeeds, SDL_MUTEX_TIMEDOUT if the wait does not succeed in the allotted time, and -1 on error.
Warning
On some platforms this function is implemented by looping with a delay of 1 ms, and so should be avoided if possible.

Definition at line 150 of file SDL_syssem.c.

151 {
152  int retval;
153 
154  if (!sem) {
155  return SDL_SetError("Passed a NULL semaphore");
156  }
157 
158  /* A timeout of 0 is an easy case */
159  if (timeout == 0) {
160  return SDL_SemTryWait(sem);
161  }
162 
163  SDL_LockMutex(sem->count_lock);
164  ++sem->waiters_count;
165  retval = 0;
166  while ((sem->count == 0) && (retval != SDL_MUTEX_TIMEDOUT)) {
167  retval = SDL_CondWaitTimeout(sem->count_nonzero,
168  sem->count_lock, timeout);
169  }
170  --sem->waiters_count;
171  if (retval == 0) {
172  --sem->count;
173  }
174  SDL_UnlockMutex(sem->count_lock);
175 
176  return retval;
177 }
#define SDL_CondWaitTimeout
GLbitfield GLuint64 timeout
int SDL_SemTryWait(SDL_sem *sem)
Definition: SDL_syssem.c:130

References NULL, retval, SDL_CondWaitTimeout, SDL_Delay, SDL_GetTicks(), SDL_LockMutex, SDL_MUTEX_MAXWAIT, SDL_MUTEX_TIMEDOUT, SDL_SemTryWait(), SDL_SemWait(), SDL_SetError, SDL_TICKS_PASSED, SDL_UnlockMutex, and sem.

Referenced by SDL_SemWait().

◆ SDL_TryLockMutex()

int SDL_TryLockMutex ( SDL_mutex mutex)

Try to lock the mutex

Returns
0, SDL_MUTEX_TIMEDOUT, or -1 on error

Definition at line 103 of file SDL_sysmutex.c.

104 {
105 #if SDL_THREADS_DISABLED
106  return 0;
107 #else
108  int retval = 0;
109  SDL_threadID this_thread;
110 
111  if (mutex == NULL) {
112  return SDL_SetError("Passed a NULL mutex");
113  }
114 
115  this_thread = SDL_ThreadID();
116  if (mutex->owner == this_thread) {
117  ++mutex->recursive;
118  } else {
119  /* The order of operations is important.
120  We set the locking thread id after we obtain the lock
121  so unlocks from other threads will fail.
122  */
124  if (retval == 0) {
125  mutex->owner = this_thread;
126  mutex->recursive = 0;
127  }
128  }
129 
130  return retval;
131 #endif /* SDL_THREADS_DISABLED */
132 }

References SDL_mutex::cpp_mutex, SDL_mutex::id, mutex, NULL, SDL_mutex::owner, SDL_mutex::recursive, retval, SDL_MUTEX_TIMEDOUT, SDL_SemWait, SDL_SetError, SDL_ThreadID, and SDL_mutex::sem.

◆ SDL_UnlockMutex()

int SDL_UnlockMutex ( SDL_mutex mutex)

Definition at line 162 of file SDL_sysmutex.c.

163 {
164  if (mutex == NULL) {
165  return SDL_SetError("Passed a NULL mutex");
166  }
167 
168 #if FAKE_RECURSIVE_MUTEX
169  /* We can only unlock the mutex if we own it */
170  if (pthread_self() == mutex->owner) {
171  if (mutex->recursive) {
172  --mutex->recursive;
173  } else {
174  /* The order of operations is important.
175  First reset the owner so another thread doesn't lock
176  the mutex and set the ownership before we reset it,
177  then release the lock semaphore.
178  */
179  mutex->owner = 0;
180  pthread_mutex_unlock(&mutex->id);
181  }
182  } else {
183  return SDL_SetError("mutex not owned by this thread");
184  }
185 
186 #else
187  if (pthread_mutex_unlock(&mutex->id) != 0) {
188  return SDL_SetError("pthread_mutex_unlock() failed");
189  }
190 #endif /* FAKE_RECURSIVE_MUTEX */
191 
192  return 0;
193 }
pthread_mutex_t id
Definition: SDL_sysmutex.c:35

References SDL_mutex::id, mutex, NULL, SDL_mutex::owner, SDL_mutex::recursive, and SDL_SetError.