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

#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.

Referenced by SDL_CondWait(), SDL_CondWaitTimeout(), SDL_SemWait(), SDL_SemWaitTimeout(), and SDL_TimerThread().

#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.

Referenced by SDL_CondWaitTimeout(), SDL_SemTryWait(), SDL_SemWaitTimeout(), SDL_TryLockMutex(), and TestWaitTimeout().

#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.

#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

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.

References SDL_cond::cond, SDL_cond::cpp_cond, i, SDL_cond::lock, retval, SDL_LockMutex, SDL_SemPost, SDL_SemWait, SDL_SetError, SDL_UnlockMutex, SDL_cond::signals, SDL_cond::wait_done, SDL_cond::wait_sem, and SDL_cond::waiting.

{
if (!cond) {
return SDL_SetError("Passed a NULL condition variable");
}
/* If there are waiting threads not already signalled, then
signal the condition and wait for the thread to respond.
*/
if (cond->waiting > cond->signals) {
int i, num_waiting;
num_waiting = (cond->waiting - cond->signals);
cond->signals = cond->waiting;
for (i = 0; i < num_waiting; ++i) {
}
/* Now all released threads are blocked here, waiting for us.
Collect them all (and win fabulous prizes!) :-)
*/
for (i = 0; i < num_waiting; ++i) {
}
} else {
}
return 0;
}
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.

References SDL_cond::cond, SDL_cond::cpp_cond, SDL_cond::lock, retval, SDL_LockMutex, SDL_SemPost, SDL_SemWait, SDL_SetError, SDL_UnlockMutex, SDL_cond::signals, SDL_cond::wait_done, SDL_cond::wait_sem, and SDL_cond::waiting.

{
if (!cond) {
return SDL_SetError("Passed a NULL condition variable");
}
/* If there are waiting threads not already signalled, then
signal the condition and wait for the thread to respond.
*/
if (cond->waiting > cond->signals) {
++cond->signals;
} else {
}
return 0;
}
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.

References SDL_cond::cond, SDL_mutex::id, SDL_CondWaitTimeout, SDL_MUTEX_MAXWAIT, and SDL_SetError.

{
return SDL_CondWaitTimeout(cond, mutex, SDL_MUTEX_MAXWAIT);
}
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.

References SDL_cond::cond, SDL_cond::cpp_cond, SDL_mutex::cpp_mutex, SDL_mutex::id, SDL_cond::lock, NULL, retval, SDL_LockMutex, SDL_MUTEX_MAXWAIT, SDL_MUTEX_TIMEDOUT, SDL_SemPost, SDL_SemWait, SDL_SemWaitTimeout, SDL_SetError, SDL_UnlockMutex, SDL_cond::signals, SDL_cond::wait_done, SDL_cond::wait_sem, and SDL_cond::waiting.

{
int retval;
if (!cond) {
return SDL_SetError("Passed a NULL condition variable");
}
/* Obtain the protection mutex, and increment the number of waiters.
This allows the signal mechanism to only perform a signal if there
are waiting threads.
*/
++cond->waiting;
/* Unlock the mutex, as is required by condition variable semantics */
/* Wait for a signal */
if (ms == SDL_MUTEX_MAXWAIT) {
retval = SDL_SemWait(cond->wait_sem);
} else {
retval = SDL_SemWaitTimeout(cond->wait_sem, ms);
}
/* Let the signaler know we have completed the wait, otherwise
the signaler can race ahead and get the condition semaphore
if we are stopped between the mutex unlock and semaphore wait,
giving a deadlock. See the following URL for details:
http://web.archive.org/web/20010914175514/http://www-classic.be.com/aboutbe/benewsletter/volume_III/Issue40.html#Workshop
*/
if (cond->signals > 0) {
/* If we timed out, we need to eat a condition signal */
if (retval > 0) {
}
/* We always notify the signal thread that we are done */
/* Signal handshake complete */
--cond->signals;
}
--cond->waiting;
/* Lock the mutex, as is required by condition variable semantics */
SDL_LockMutex(mutex);
return retval;
}
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.

References SDL_cond::cond, SDL_cond::lock, NULL, SDL_CreateMutex, SDL_CreateSemaphore, SDL_DestroyCond, SDL_free, SDL_malloc, SDL_OutOfMemory, SDL_SetError, SDL_cond::signals, SDL_cond::wait_done, SDL_cond::wait_sem, and SDL_cond::waiting.

{
SDL_cond *cond;
cond = (SDL_cond *) SDL_malloc(sizeof(SDL_cond));
if (cond) {
cond->lock = SDL_CreateMutex();
cond->waiting = cond->signals = 0;
if (!cond->lock || !cond->wait_sem || !cond->wait_done) {
cond = NULL;
}
} else {
}
return (cond);
}
SDL_mutex* SDL_CreateMutex ( void  )

Create a mutex, initialized unlocked.

Definition at line 38 of file SDL_sysmutex.c.

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.

{
/* Allocate mutex memory */
mutex = (SDL_mutex *) SDL_malloc(sizeof(*mutex));
if (mutex) {
/* Create the mutex semaphore, with initial value 1 */
mutex->sem = SDL_CreateSemaphore(1);
mutex->recursive = 0;
mutex->owner = 0;
if (!mutex->sem) {
SDL_free(mutex);
mutex = NULL;
}
} else {
}
return mutex;
}
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.

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

{
SDL_sem *sem;
sem = (SDL_sem *) SDL_malloc(sizeof(*sem));
if (!sem) {
return NULL;
}
sem->count = initial_value;
sem->waiters_count = 0;
sem->count_lock = SDL_CreateMutex();
sem->count_nonzero = SDL_CreateCond();
if (!sem->count_lock || !sem->count_nonzero) {
return NULL;
}
return sem;
}
void SDL_DestroyCond ( SDL_cond cond)

Destroy a condition variable.

Definition at line 64 of file SDL_syscond.c.

References SDL_cond::cond, SDL_cond::lock, SDL_DestroyMutex, SDL_DestroySemaphore, SDL_free, SDL_cond::wait_done, and SDL_cond::wait_sem.

{
if (cond) {
if (cond->wait_sem) {
}
if (cond->wait_done) {
}
if (cond->lock) {
}
SDL_free(cond);
}
}
void SDL_DestroyMutex ( SDL_mutex mutex)

Destroy a mutex.

Definition at line 61 of file SDL_sysmutex.c.

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

{
if (mutex) {
if (mutex->sem) {
}
SDL_free(mutex);
}
}
void SDL_DestroySemaphore ( SDL_sem *  sem)

Destroy a semaphore.

Definition at line 111 of file SDL_syssem.c.

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

{
if (sem) {
sem->count = 0xFFFFFFFF;
while (sem->waiters_count > 0) {
SDL_CondSignal(sem->count_nonzero);
SDL_Delay(10);
}
SDL_DestroyCond(sem->count_nonzero);
if (sem->count_lock) {
SDL_LockMutex(sem->count_lock);
SDL_UnlockMutex(sem->count_lock);
SDL_DestroyMutex(sem->count_lock);
}
}
}
int SDL_LockMutex ( SDL_mutex mutex)

Definition at line 73 of file SDL_sysmutex.c.

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

{
#if SDL_THREADS_DISABLED
return 0;
#else
SDL_threadID this_thread;
if (mutex == NULL) {
return SDL_SetError("Passed a NULL mutex");
}
this_thread = SDL_ThreadID();
if (mutex->owner == this_thread) {
++mutex->recursive;
} else {
/* The order of operations is important.
We set the locking thread id after we obtain the lock
so unlocks from other threads will fail.
*/
SDL_SemWait(mutex->sem);
mutex->owner = this_thread;
mutex->recursive = 0;
}
return 0;
#endif /* SDL_THREADS_DISABLED */
}
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.

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

{
if (!sem) {
return SDL_SetError("Passed a NULL semaphore");
}
SDL_LockMutex(sem->count_lock);
if (sem->waiters_count > 0) {
SDL_CondSignal(sem->count_nonzero);
}
++sem->count;
SDL_UnlockMutex(sem->count_lock);
return 0;
}
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.

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

{
int retval;
if (!sem) {
return SDL_SetError("Passed a NULL semaphore");
}
SDL_LockMutex(sem->count_lock);
if (sem->count > 0) {
--sem->count;
retval = 0;
}
SDL_UnlockMutex(sem->count_lock);
return retval;
}
Uint32 SDL_SemValue ( SDL_sem *  sem)

Returns the current count of the semaphore.

Definition at line 186 of file SDL_syssem.c.

References SDL_LockMutex, and SDL_UnlockMutex.

{
value = 0;
if (sem) {
SDL_LockMutex(sem->count_lock);
value = sem->count;
SDL_UnlockMutex(sem->count_lock);
}
return value;
}
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.

References retval, SDL_MUTEX_MAXWAIT, SDL_SemWaitTimeout, and SDL_SetError.

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.

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, and SDL_UnlockMutex.

{
int retval;
if (!sem) {
return SDL_SetError("Passed a NULL semaphore");
}
/* A timeout of 0 is an easy case */
if (timeout == 0) {
}
SDL_LockMutex(sem->count_lock);
++sem->waiters_count;
retval = 0;
while ((sem->count == 0) && (retval != SDL_MUTEX_TIMEDOUT)) {
retval = SDL_CondWaitTimeout(sem->count_nonzero,
sem->count_lock, timeout);
}
--sem->waiters_count;
if (retval == 0) {
--sem->count;
}
SDL_UnlockMutex(sem->count_lock);
return retval;
}
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.

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

{
#if SDL_THREADS_DISABLED
return 0;
#else
int retval = 0;
SDL_threadID this_thread;
if (mutex == NULL) {
return SDL_SetError("Passed a NULL mutex");
}
this_thread = SDL_ThreadID();
if (mutex->owner == this_thread) {
++mutex->recursive;
} else {
/* The order of operations is important.
We set the locking thread id after we obtain the lock
so unlocks from other threads will fail.
*/
retval = SDL_SemWait(mutex->sem);
if (retval == 0) {
mutex->owner = this_thread;
mutex->recursive = 0;
}
}
return retval;
#endif /* SDL_THREADS_DISABLED */
}
int SDL_UnlockMutex ( SDL_mutex mutex)

Definition at line 162 of file SDL_sysmutex.c.

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

{
if (mutex == NULL) {
return SDL_SetError("Passed a NULL mutex");
}
#if FAKE_RECURSIVE_MUTEX
/* We can only unlock the mutex if we own it */
if (pthread_self() == mutex->owner) {
if (mutex->recursive) {
--mutex->recursive;
} else {
/* The order of operations is important.
First reset the owner so another thread doesn't lock
the mutex and set the ownership before we reset it,
then release the lock semaphore.
*/
mutex->owner = 0;
pthread_mutex_unlock(&mutex->id);
}
} else {
return SDL_SetError("mutex not owned by this thread");
}
#else
if (pthread_mutex_unlock(&mutex->id) != 0) {
return SDL_SetError("pthread_mutex_unlock() failed");
}
#endif /* FAKE_RECURSIVE_MUTEX */
return 0;
}