SDL
2.0
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
SDL_syscond.c
Go to the documentation of this file.
1
/*
2
Simple DirectMedia Layer
3
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
4
5
This software is provided 'as-is', without any express or implied
6
warranty. In no event will the authors be held liable for any damages
7
arising from the use of this software.
8
9
Permission is granted to anyone to use this software for any purpose,
10
including commercial applications, and to alter it and redistribute it
11
freely, subject to the following restrictions:
12
13
1. The origin of this software must not be misrepresented; you must not
14
claim that you wrote the original software. If you use this software
15
in a product, an acknowledgment in the product documentation would be
16
appreciated but is not required.
17
2. Altered source versions must be plainly marked as such, and must not be
18
misrepresented as being the original software.
19
3. This notice may not be removed or altered from any source distribution.
20
*/
21
#include "../../SDL_internal.h"
22
23
/* An implementation of condition variables using semaphores and mutexes */
24
/*
25
This implementation borrows heavily from the BeOS condition variable
26
implementation, written by Christopher Tate and Owen Smith. Thanks!
27
*/
28
29
#include "
SDL_thread.h
"
30
31
struct
SDL_cond
32
{
33
SDL_mutex
*
lock
;
34
int
waiting
;
35
int
signals
;
36
SDL_sem *
wait_sem
;
37
SDL_sem *
wait_done
;
38
};
39
40
/* Create a condition variable */
41
SDL_cond
*
42
SDL_CreateCond
(
void
)
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
{
57
SDL_OutOfMemory
();
58
}
59
return
(cond);
60
}
61
62
/* Destroy a condition variable */
63
void
64
SDL_DestroyCond
(
SDL_cond
* cond)
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
}
79
80
/* Restart one of the threads that are waiting on the condition variable */
81
int
82
SDL_CondSignal
(
SDL_cond
* cond)
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
}
103
104
/* Restart all threads that are waiting on the condition variable */
105
int
106
SDL_CondBroadcast
(
SDL_cond
* cond)
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
}
137
138
/* Wait on the condition variable for at most 'ms' milliseconds.
139
The mutex must be locked before entering this function!
140
The mutex is unlocked during the wait, and locked again after the wait.
141
142
Typical use:
143
144
Thread A:
145
SDL_LockMutex(lock);
146
while ( ! condition ) {
147
SDL_CondWait(cond, lock);
148
}
149
SDL_UnlockMutex(lock);
150
151
Thread B:
152
SDL_LockMutex(lock);
153
...
154
condition = true;
155
...
156
SDL_CondSignal(cond);
157
SDL_UnlockMutex(lock);
158
*/
159
int
160
SDL_CondWaitTimeout
(
SDL_cond
* cond,
SDL_mutex
*
mutex
,
Uint32
ms)
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
}
212
213
/* Wait on the condition variable forever */
214
int
215
SDL_CondWait
(
SDL_cond
* cond,
SDL_mutex
*
mutex
)
216
{
217
return
SDL_CondWaitTimeout
(cond, mutex,
SDL_MUTEX_MAXWAIT
);
218
}
219
220
/* vi: set ts=4 sw=4 expandtab: */
src
thread
generic
SDL_syscond.c
Generated on Sun Jun 26 2022 23:07:14 for SDL by
1.8.1.2