SDL  2.0
SDL_syscond.c File Reference
#include "../../SDL_internal.h"
#include "SDL_thread.h"
+ Include dependency graph for SDL_syscond.c:

Go to the source code of this file.

Data Structures

struct  SDL_cond
 

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_CondWaitTimeout (SDL_cond *cond, SDL_mutex *mutex, Uint32 ms)
 
int SDL_CondWait (SDL_cond *cond, SDL_mutex *mutex)
 

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.

References i, SDL_cond::lock, 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.

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_LockMutex
SDL_mutex * lock
Definition: SDL_syscond.c:33
int waiting
Definition: SDL_syscond.c:34
#define SDL_SemPost
int signals
Definition: SDL_syscond.c:35
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
#define SDL_SetError
SDL_sem * wait_done
Definition: SDL_syscond.c:37
#define SDL_SemWait
SDL_sem * wait_sem
Definition: SDL_syscond.c:36
#define 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.

References SDL_cond::lock, 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.

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 }
#define SDL_LockMutex
SDL_mutex * lock
Definition: SDL_syscond.c:33
int waiting
Definition: SDL_syscond.c:34
#define SDL_SemPost
int signals
Definition: SDL_syscond.c:35
#define SDL_SetError
SDL_sem * wait_done
Definition: SDL_syscond.c:37
#define SDL_SemWait
SDL_sem * wait_sem
Definition: SDL_syscond.c:36
#define 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.

References SDL_CondWaitTimeout(), and SDL_MUTEX_MAXWAIT.

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

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

References SDL_cond::lock, retval, SDL_LockMutex, SDL_MUTEX_MAXWAIT, 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.

Referenced by SDL_CondWait().

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 */
177  SDL_UnlockMutex(mutex);
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 */
208  SDL_LockMutex(mutex);
209 
210  return retval;
211 }
#define SDL_LockMutex
SDL_mutex * lock
Definition: SDL_syscond.c:33
int waiting
Definition: SDL_syscond.c:34
#define SDL_SemPost
SDL_bool retval
#define SDL_SemWaitTimeout
#define SDL_MUTEX_MAXWAIT
Definition: SDL_mutex.h:49
int signals
Definition: SDL_syscond.c:35
#define SDL_SetError
SDL_sem * wait_done
Definition: SDL_syscond.c:37
#define SDL_SemWait
SDL_sem * wait_sem
Definition: SDL_syscond.c:36
#define SDL_UnlockMutex

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

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

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) {
53  SDL_DestroyCond(cond);
54  cond = NULL;
55  }
56  } else {
58  }
59  return (cond);
60 }
#define SDL_CreateSemaphore
SDL_mutex * lock
Definition: SDL_syscond.c:33
#define SDL_CreateMutex
int waiting
Definition: SDL_syscond.c:34
int signals
Definition: SDL_syscond.c:35
#define NULL
Definition: begin_code.h:164
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_sem * wait_done
Definition: SDL_syscond.c:37
SDL_sem * wait_sem
Definition: SDL_syscond.c:36
#define SDL_malloc
void SDL_DestroyCond(SDL_cond *cond)
Definition: SDL_syscond.c:64

◆ SDL_DestroyCond()

void SDL_DestroyCond ( SDL_cond cond)

Destroy a condition variable.

Definition at line 64 of file SDL_syscond.c.

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

Referenced by SDL_CreateCond().

65 {
66  if (cond) {
67  if (cond->wait_sem) {
69  }
70  if (cond->wait_done) {
72  }
73  if (cond->lock) {
74  SDL_DestroyMutex(cond->lock);
75  }
76  SDL_free(cond);
77  }
78 }
SDL_mutex * lock
Definition: SDL_syscond.c:33
#define SDL_free
#define SDL_DestroyMutex
SDL_sem * wait_done
Definition: SDL_syscond.c:37
#define SDL_DestroySemaphore
SDL_sem * wait_sem
Definition: SDL_syscond.c:36