Skip to content
This repository has been archived by the owner on Feb 11, 2021. It is now read-only.

Latest commit

 

History

History
223 lines (192 loc) · 6.04 KB

SDL_syscond.c

File metadata and controls

223 lines (192 loc) · 6.04 KB
 
Nov 23, 2005
Nov 23, 2005
1
2
/*
SDL - Simple DirectMedia Layer
Feb 1, 2006
Feb 1, 2006
3
Copyright (C) 1997-2006 Sam Lantinga
Nov 23, 2005
Nov 23, 2005
4
5
This library is free software; you can redistribute it and/or
Feb 1, 2006
Feb 1, 2006
6
modify it under the terms of the GNU Lesser General Public
Nov 23, 2005
Nov 23, 2005
7
License as published by the Free Software Foundation; either
Feb 1, 2006
Feb 1, 2006
8
version 2.1 of the License, or (at your option) any later version.
Nov 23, 2005
Nov 23, 2005
9
10
11
12
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Feb 1, 2006
Feb 1, 2006
13
Lesser General Public License for more details.
Nov 23, 2005
Nov 23, 2005
14
Feb 1, 2006
Feb 1, 2006
15
16
17
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Nov 23, 2005
Nov 23, 2005
18
19
20
21
Sam Lantinga
slouken@libsdl.org
*/
Feb 21, 2006
Feb 21, 2006
22
#include "SDL_config.h"
Nov 23, 2005
Nov 23, 2005
23
24
25
26
27
28
29
30
31
32
33
/* An implementation of condition variables using semaphores and mutexes */
/*
This implementation borrows heavily from the BeOS condition variable
implementation, written by Christopher Tate and Owen Smith. Thanks!
*/
#include "SDL_thread.h"
struct SDL_cond
{
May 28, 2006
May 28, 2006
34
35
36
37
38
SDL_mutex *lock;
int waiting;
int signals;
SDL_sem *wait_sem;
SDL_sem *wait_done;
Nov 23, 2005
Nov 23, 2005
39
40
41
};
/* Create a condition variable */
May 28, 2006
May 28, 2006
42
DECLSPEC SDL_cond *SDLCALL
May 29, 2006
May 29, 2006
43
SDL_CreateCond(void)
Nov 23, 2005
Nov 23, 2005
44
{
May 28, 2006
May 28, 2006
45
46
SDL_cond *cond;
May 29, 2006
May 29, 2006
47
cond = (SDL_cond *) SDL_malloc(sizeof(SDL_cond));
May 28, 2006
May 28, 2006
48
if (cond) {
May 29, 2006
May 29, 2006
49
50
51
cond->lock = SDL_CreateMutex();
cond->wait_sem = SDL_CreateSemaphore(0);
cond->wait_done = SDL_CreateSemaphore(0);
May 28, 2006
May 28, 2006
52
53
cond->waiting = cond->signals = 0;
if (!cond->lock || !cond->wait_sem || !cond->wait_done) {
May 29, 2006
May 29, 2006
54
SDL_DestroyCond(cond);
May 28, 2006
May 28, 2006
55
56
57
cond = NULL;
}
} else {
May 29, 2006
May 29, 2006
58
SDL_OutOfMemory();
May 28, 2006
May 28, 2006
59
60
}
return (cond);
Nov 23, 2005
Nov 23, 2005
61
62
63
}
/* Destroy a condition variable */
May 28, 2006
May 28, 2006
64
DECLSPEC void SDLCALL
May 29, 2006
May 29, 2006
65
SDL_DestroyCond(SDL_cond * cond)
Nov 23, 2005
Nov 23, 2005
66
{
May 28, 2006
May 28, 2006
67
68
if (cond) {
if (cond->wait_sem) {
May 29, 2006
May 29, 2006
69
SDL_DestroySemaphore(cond->wait_sem);
May 28, 2006
May 28, 2006
70
71
}
if (cond->wait_done) {
May 29, 2006
May 29, 2006
72
SDL_DestroySemaphore(cond->wait_done);
May 28, 2006
May 28, 2006
73
74
}
if (cond->lock) {
May 29, 2006
May 29, 2006
75
SDL_DestroyMutex(cond->lock);
May 28, 2006
May 28, 2006
76
}
May 29, 2006
May 29, 2006
77
SDL_free(cond);
May 28, 2006
May 28, 2006
78
}
Nov 23, 2005
Nov 23, 2005
79
80
81
}
/* Restart one of the threads that are waiting on the condition variable */
May 28, 2006
May 28, 2006
82
DECLSPEC int SDLCALL
May 29, 2006
May 29, 2006
83
SDL_CondSignal(SDL_cond * cond)
Nov 23, 2005
Nov 23, 2005
84
{
May 28, 2006
May 28, 2006
85
if (!cond) {
May 29, 2006
May 29, 2006
86
SDL_SetError("Passed a NULL condition variable");
May 28, 2006
May 28, 2006
87
88
89
90
91
92
return -1;
}
/* If there are waiting threads not already signalled, then
signal the condition and wait for the thread to respond.
*/
May 29, 2006
May 29, 2006
93
SDL_LockMutex(cond->lock);
May 28, 2006
May 28, 2006
94
95
if (cond->waiting > cond->signals) {
++cond->signals;
May 29, 2006
May 29, 2006
96
97
98
SDL_SemPost(cond->wait_sem);
SDL_UnlockMutex(cond->lock);
SDL_SemWait(cond->wait_done);
May 28, 2006
May 28, 2006
99
} else {
May 29, 2006
May 29, 2006
100
SDL_UnlockMutex(cond->lock);
May 28, 2006
May 28, 2006
101
102
103
}
return 0;
Nov 23, 2005
Nov 23, 2005
104
105
106
}
/* Restart all threads that are waiting on the condition variable */
May 28, 2006
May 28, 2006
107
DECLSPEC int SDLCALL
May 29, 2006
May 29, 2006
108
SDL_CondBroadcast(SDL_cond * cond)
Nov 23, 2005
Nov 23, 2005
109
{
May 28, 2006
May 28, 2006
110
if (!cond) {
May 29, 2006
May 29, 2006
111
SDL_SetError("Passed a NULL condition variable");
May 28, 2006
May 28, 2006
112
113
114
115
116
117
return -1;
}
/* If there are waiting threads not already signalled, then
signal the condition and wait for the thread to respond.
*/
May 29, 2006
May 29, 2006
118
SDL_LockMutex(cond->lock);
May 28, 2006
May 28, 2006
119
120
121
122
123
124
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) {
May 29, 2006
May 29, 2006
125
SDL_SemPost(cond->wait_sem);
May 28, 2006
May 28, 2006
126
127
128
129
}
/* Now all released threads are blocked here, waiting for us.
Collect them all (and win fabulous prizes!) :-)
*/
May 29, 2006
May 29, 2006
130
SDL_UnlockMutex(cond->lock);
May 28, 2006
May 28, 2006
131
for (i = 0; i < num_waiting; ++i) {
May 29, 2006
May 29, 2006
132
SDL_SemWait(cond->wait_done);
May 28, 2006
May 28, 2006
133
134
}
} else {
May 29, 2006
May 29, 2006
135
SDL_UnlockMutex(cond->lock);
May 28, 2006
May 28, 2006
136
137
138
}
return 0;
Nov 23, 2005
Nov 23, 2005
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
}
/* Wait on the condition variable for at most 'ms' milliseconds.
The mutex must be locked before entering this function!
The mutex is unlocked during the wait, and locked again after the wait.
Typical use:
Thread A:
SDL_LockMutex(lock);
while ( ! condition ) {
SDL_CondWait(cond);
}
SDL_UnlockMutex(lock);
Thread B:
SDL_LockMutex(lock);
...
condition = true;
...
SDL_UnlockMutex(lock);
*/
May 28, 2006
May 28, 2006
161
DECLSPEC int SDLCALL
May 29, 2006
May 29, 2006
162
SDL_CondWaitTimeout(SDL_cond * cond, SDL_mutex * mutex, Uint32 ms)
Nov 23, 2005
Nov 23, 2005
163
{
May 28, 2006
May 28, 2006
164
165
166
int retval;
if (!cond) {
May 29, 2006
May 29, 2006
167
SDL_SetError("Passed a NULL condition variable");
May 28, 2006
May 28, 2006
168
169
170
171
172
173
174
return -1;
}
/* 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.
*/
May 29, 2006
May 29, 2006
175
SDL_LockMutex(cond->lock);
May 28, 2006
May 28, 2006
176
++cond->waiting;
May 29, 2006
May 29, 2006
177
SDL_UnlockMutex(cond->lock);
May 28, 2006
May 28, 2006
178
179
/* Unlock the mutex, as is required by condition variable semantics */
May 29, 2006
May 29, 2006
180
SDL_UnlockMutex(mutex);
May 28, 2006
May 28, 2006
181
182
183
/* Wait for a signal */
if (ms == SDL_MUTEX_MAXWAIT) {
May 29, 2006
May 29, 2006
184
retval = SDL_SemWait(cond->wait_sem);
May 28, 2006
May 28, 2006
185
} else {
May 29, 2006
May 29, 2006
186
retval = SDL_SemWaitTimeout(cond->wait_sem, ms);
May 28, 2006
May 28, 2006
187
188
189
190
191
192
193
194
}
/* 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://www-classic.be.com/aboutbe/benewsletter/volume_III/Issue40.html
*/
May 29, 2006
May 29, 2006
195
SDL_LockMutex(cond->lock);
May 28, 2006
May 28, 2006
196
197
198
if (cond->signals > 0) {
/* If we timed out, we need to eat a condition signal */
if (retval > 0) {
May 29, 2006
May 29, 2006
199
SDL_SemWait(cond->wait_sem);
May 28, 2006
May 28, 2006
200
201
}
/* We always notify the signal thread that we are done */
May 29, 2006
May 29, 2006
202
SDL_SemPost(cond->wait_done);
May 28, 2006
May 28, 2006
203
204
205
206
207
/* Signal handshake complete */
--cond->signals;
}
--cond->waiting;
May 29, 2006
May 29, 2006
208
SDL_UnlockMutex(cond->lock);
May 28, 2006
May 28, 2006
209
210
/* Lock the mutex, as is required by condition variable semantics */
May 29, 2006
May 29, 2006
211
SDL_LockMutex(mutex);
May 28, 2006
May 28, 2006
212
213
return retval;
Nov 23, 2005
Nov 23, 2005
214
215
216
}
/* Wait on the condition variable forever */
May 28, 2006
May 28, 2006
217
DECLSPEC int SDLCALL
May 29, 2006
May 29, 2006
218
SDL_CondWait(SDL_cond * cond, SDL_mutex * mutex)
Nov 23, 2005
Nov 23, 2005
219
{
May 29, 2006
May 29, 2006
220
return SDL_CondWaitTimeout(cond, mutex, SDL_MUTEX_MAXWAIT);
Nov 23, 2005
Nov 23, 2005
221
}
May 28, 2006
May 28, 2006
222
223
/* vi: set ts=4 sw=4 expandtab: */