Mercurial > sdl-ios-xcode
annotate src/thread/generic/SDL_syscond.c @ 1338:604d73db6802
Removed uses of stdlib.h and string.h
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Tue, 07 Feb 2006 09:29:18 +0000 |
parents | 3692456e7b0f |
children | c71e05b4dc2e |
rev | line source |
---|---|
0 | 1 /* |
2 SDL - Simple DirectMedia Layer | |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
3 Copyright (C) 1997-2006 Sam Lantinga |
0 | 4 |
5 This library is free software; you can redistribute it and/or | |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
6 modify it under the terms of the GNU Lesser General Public |
0 | 7 License as published by the Free Software Foundation; either |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
8 version 2.1 of the License, or (at your option) any later version. |
0 | 9 |
10 This library is distributed in the hope that it will be useful, | |
11 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
13 Lesser General Public License for more details. |
0 | 14 |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
15 You should have received a copy of the GNU Lesser General Public |
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
16 License along with this library; if not, write to the Free Software |
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
0 | 18 |
19 Sam Lantinga | |
252
e8157fcb3114
Updated the source with the correct e-mail address
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
20 slouken@libsdl.org |
0 | 21 */ |
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 | |
1338
604d73db6802
Removed uses of stdlib.h and string.h
Sam Lantinga <slouken@libsdl.org>
parents:
1336
diff
changeset
|
29 #include "SDL_stdlib.h" |
0 | 30 #include "SDL_error.h" |
31 #include "SDL_thread.h" | |
32 | |
33 struct SDL_cond | |
34 { | |
35 SDL_mutex *lock; | |
36 int waiting; | |
37 int signals; | |
38 SDL_sem *wait_sem; | |
39 SDL_sem *wait_done; | |
40 }; | |
41 | |
42 /* Create a condition variable */ | |
43 SDL_cond * SDL_CreateCond(void) | |
44 { | |
45 SDL_cond *cond; | |
46 | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
47 cond = (SDL_cond *) SDL_malloc(sizeof(SDL_cond)); |
0 | 48 if ( cond ) { |
49 cond->lock = SDL_CreateMutex(); | |
50 cond->wait_sem = SDL_CreateSemaphore(0); | |
51 cond->wait_done = SDL_CreateSemaphore(0); | |
52 cond->waiting = cond->signals = 0; | |
53 if ( ! cond->lock || ! cond->wait_sem || ! cond->wait_done ) { | |
54 SDL_DestroyCond(cond); | |
55 cond = NULL; | |
56 } | |
57 } else { | |
58 SDL_OutOfMemory(); | |
59 } | |
60 return(cond); | |
61 } | |
62 | |
63 /* Destroy a condition variable */ | |
64 void 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 } | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1330
diff
changeset
|
76 SDL_free(cond); |
0 | 77 } |
78 } | |
79 | |
80 /* Restart one of the threads that are waiting on the condition variable */ | |
81 int SDL_CondSignal(SDL_cond *cond) | |
82 { | |
83 if ( ! cond ) { | |
84 SDL_SetError("Passed a NULL condition variable"); | |
85 return -1; | |
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 SDL_CondBroadcast(SDL_cond *cond) | |
106 { | |
107 if ( ! cond ) { | |
108 SDL_SetError("Passed a NULL condition variable"); | |
109 return -1; | |
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); | |
148 } | |
149 SDL_UnlockMutex(lock); | |
150 | |
151 Thread B: | |
152 SDL_LockMutex(lock); | |
153 ... | |
154 condition = true; | |
155 ... | |
156 SDL_UnlockMutex(lock); | |
157 */ | |
158 int SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms) | |
159 { | |
160 int retval; | |
161 | |
162 if ( ! cond ) { | |
163 SDL_SetError("Passed a NULL condition variable"); | |
164 return -1; | |
165 } | |
166 | |
167 /* Obtain the protection mutex, and increment the number of waiters. | |
168 This allows the signal mechanism to only perform a signal if there | |
169 are waiting threads. | |
170 */ | |
171 SDL_LockMutex(cond->lock); | |
172 ++cond->waiting; | |
173 SDL_UnlockMutex(cond->lock); | |
174 | |
175 /* Unlock the mutex, as is required by condition variable semantics */ | |
176 SDL_UnlockMutex(mutex); | |
177 | |
178 /* Wait for a signal */ | |
179 if ( ms == SDL_MUTEX_MAXWAIT ) { | |
180 retval = SDL_SemWait(cond->wait_sem); | |
181 } else { | |
182 retval = SDL_SemWaitTimeout(cond->wait_sem, ms); | |
183 } | |
184 | |
185 /* Let the signaler know we have completed the wait, otherwise | |
186 the signaler can race ahead and get the condition semaphore | |
187 if we are stopped between the mutex unlock and semaphore wait, | |
188 giving a deadlock. See the following URL for details: | |
189 http://www-classic.be.com/aboutbe/benewsletter/volume_III/Issue40.html | |
190 */ | |
191 SDL_LockMutex(cond->lock); | |
192 if ( cond->signals > 0 ) { | |
193 /* If we timed out, we need to eat a condition signal */ | |
194 if ( retval > 0 ) { | |
195 SDL_SemWait(cond->wait_sem); | |
196 } | |
197 /* We always notify the signal thread that we are done */ | |
198 SDL_SemPost(cond->wait_done); | |
199 | |
200 /* Signal handshake complete */ | |
201 --cond->signals; | |
202 } | |
203 --cond->waiting; | |
204 SDL_UnlockMutex(cond->lock); | |
205 | |
206 /* Lock the mutex, as is required by condition variable semantics */ | |
207 SDL_LockMutex(mutex); | |
208 | |
209 return retval; | |
210 } | |
211 | |
212 /* Wait on the condition variable forever */ | |
213 int SDL_CondWait(SDL_cond *cond, SDL_mutex *mutex) | |
214 { | |
215 return SDL_CondWaitTimeout(cond, mutex, SDL_MUTEX_MAXWAIT); | |
216 } |