Mercurial > sdl-ios-xcode
comparison src/thread/dc/SDL_syscond.c @ 1895:c121d94672cb
SDL 1.2 is moving to a branch, and SDL 1.3 is becoming the head.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Mon, 10 Jul 2006 21:04:37 +0000 |
parents | d910939febfa |
children | 99210400e8b9 |
comparison
equal
deleted
inserted
replaced
1894:c69cee13dd76 | 1895:c121d94672cb |
---|---|
29 | 29 |
30 #include "SDL_thread.h" | 30 #include "SDL_thread.h" |
31 | 31 |
32 struct SDL_cond | 32 struct SDL_cond |
33 { | 33 { |
34 SDL_mutex *lock; | 34 SDL_mutex *lock; |
35 int waiting; | 35 int waiting; |
36 int signals; | 36 int signals; |
37 SDL_sem *wait_sem; | 37 SDL_sem *wait_sem; |
38 SDL_sem *wait_done; | 38 SDL_sem *wait_done; |
39 }; | 39 }; |
40 | 40 |
41 /* Create a condition variable */ | 41 /* Create a condition variable */ |
42 SDL_cond * SDL_CreateCond(void) | 42 SDL_cond * |
43 { | 43 SDL_CreateCond(void) |
44 SDL_cond *cond; | 44 { |
45 | 45 SDL_cond *cond; |
46 cond = (SDL_cond *) SDL_malloc(sizeof(SDL_cond)); | 46 |
47 if ( cond ) { | 47 cond = (SDL_cond *) SDL_malloc(sizeof(SDL_cond)); |
48 cond->lock = SDL_CreateMutex(); | 48 if (cond) { |
49 cond->wait_sem = SDL_CreateSemaphore(0); | 49 cond->lock = SDL_CreateMutex(); |
50 cond->wait_done = SDL_CreateSemaphore(0); | 50 cond->wait_sem = SDL_CreateSemaphore(0); |
51 cond->waiting = cond->signals = 0; | 51 cond->wait_done = SDL_CreateSemaphore(0); |
52 if ( ! cond->lock || ! cond->wait_sem || ! cond->wait_done ) { | 52 cond->waiting = cond->signals = 0; |
53 SDL_DestroyCond(cond); | 53 if (!cond->lock || !cond->wait_sem || !cond->wait_done) { |
54 cond = NULL; | 54 SDL_DestroyCond(cond); |
55 } | 55 cond = NULL; |
56 } else { | 56 } |
57 SDL_OutOfMemory(); | 57 } else { |
58 } | 58 SDL_OutOfMemory(); |
59 return(cond); | 59 } |
60 return (cond); | |
60 } | 61 } |
61 | 62 |
62 /* Destroy a condition variable */ | 63 /* Destroy a condition variable */ |
63 void SDL_DestroyCond(SDL_cond *cond) | 64 void |
64 { | 65 SDL_DestroyCond(SDL_cond * cond) |
65 if ( cond ) { | 66 { |
66 if ( cond->wait_sem ) { | 67 if (cond) { |
67 SDL_DestroySemaphore(cond->wait_sem); | 68 if (cond->wait_sem) { |
68 } | 69 SDL_DestroySemaphore(cond->wait_sem); |
69 if ( cond->wait_done ) { | 70 } |
70 SDL_DestroySemaphore(cond->wait_done); | 71 if (cond->wait_done) { |
71 } | 72 SDL_DestroySemaphore(cond->wait_done); |
72 if ( cond->lock ) { | 73 } |
73 SDL_DestroyMutex(cond->lock); | 74 if (cond->lock) { |
74 } | 75 SDL_DestroyMutex(cond->lock); |
75 SDL_free(cond); | 76 } |
76 } | 77 SDL_free(cond); |
78 } | |
77 } | 79 } |
78 | 80 |
79 /* Restart one of the threads that are waiting on the condition variable */ | 81 /* Restart one of the threads that are waiting on the condition variable */ |
80 int SDL_CondSignal(SDL_cond *cond) | 82 int |
81 { | 83 SDL_CondSignal(SDL_cond * cond) |
82 if ( ! cond ) { | 84 { |
83 SDL_SetError("Passed a NULL condition variable"); | 85 if (!cond) { |
84 return -1; | 86 SDL_SetError("Passed a NULL condition variable"); |
85 } | 87 return -1; |
86 | 88 } |
87 /* If there are waiting threads not already signalled, then | 89 |
88 signal the condition and wait for the thread to respond. | 90 /* If there are waiting threads not already signalled, then |
89 */ | 91 signal the condition and wait for the thread to respond. |
90 SDL_LockMutex(cond->lock); | 92 */ |
91 if ( cond->waiting > cond->signals ) { | 93 SDL_LockMutex(cond->lock); |
92 ++cond->signals; | 94 if (cond->waiting > cond->signals) { |
93 SDL_SemPost(cond->wait_sem); | 95 ++cond->signals; |
94 SDL_UnlockMutex(cond->lock); | 96 SDL_SemPost(cond->wait_sem); |
95 SDL_SemWait(cond->wait_done); | 97 SDL_UnlockMutex(cond->lock); |
96 } else { | 98 SDL_SemWait(cond->wait_done); |
97 SDL_UnlockMutex(cond->lock); | 99 } else { |
98 } | 100 SDL_UnlockMutex(cond->lock); |
99 | 101 } |
100 return 0; | 102 |
103 return 0; | |
101 } | 104 } |
102 | 105 |
103 /* Restart all threads that are waiting on the condition variable */ | 106 /* Restart all threads that are waiting on the condition variable */ |
104 int SDL_CondBroadcast(SDL_cond *cond) | 107 int |
105 { | 108 SDL_CondBroadcast(SDL_cond * cond) |
106 if ( ! cond ) { | 109 { |
107 SDL_SetError("Passed a NULL condition variable"); | 110 if (!cond) { |
108 return -1; | 111 SDL_SetError("Passed a NULL condition variable"); |
109 } | 112 return -1; |
110 | 113 } |
111 /* If there are waiting threads not already signalled, then | 114 |
112 signal the condition and wait for the thread to respond. | 115 /* If there are waiting threads not already signalled, then |
113 */ | 116 signal the condition and wait for the thread to respond. |
114 SDL_LockMutex(cond->lock); | 117 */ |
115 if ( cond->waiting > cond->signals ) { | 118 SDL_LockMutex(cond->lock); |
116 int i, num_waiting; | 119 if (cond->waiting > cond->signals) { |
117 | 120 int i, num_waiting; |
118 num_waiting = (cond->waiting - cond->signals); | 121 |
119 cond->signals = cond->waiting; | 122 num_waiting = (cond->waiting - cond->signals); |
120 for ( i=0; i<num_waiting; ++i ) { | 123 cond->signals = cond->waiting; |
121 SDL_SemPost(cond->wait_sem); | 124 for (i = 0; i < num_waiting; ++i) { |
122 } | 125 SDL_SemPost(cond->wait_sem); |
123 /* Now all released threads are blocked here, waiting for us. | 126 } |
124 Collect them all (and win fabulous prizes!) :-) | 127 /* Now all released threads are blocked here, waiting for us. |
125 */ | 128 Collect them all (and win fabulous prizes!) :-) |
126 SDL_UnlockMutex(cond->lock); | 129 */ |
127 for ( i=0; i<num_waiting; ++i ) { | 130 SDL_UnlockMutex(cond->lock); |
128 SDL_SemWait(cond->wait_done); | 131 for (i = 0; i < num_waiting; ++i) { |
129 } | 132 SDL_SemWait(cond->wait_done); |
130 } else { | 133 } |
131 SDL_UnlockMutex(cond->lock); | 134 } else { |
132 } | 135 SDL_UnlockMutex(cond->lock); |
133 | 136 } |
134 return 0; | 137 |
138 return 0; | |
135 } | 139 } |
136 | 140 |
137 /* Wait on the condition variable for at most 'ms' milliseconds. | 141 /* Wait on the condition variable for at most 'ms' milliseconds. |
138 The mutex must be locked before entering this function! | 142 The mutex must be locked before entering this function! |
139 The mutex is unlocked during the wait, and locked again after the wait. | 143 The mutex is unlocked during the wait, and locked again after the wait. |
152 ... | 156 ... |
153 condition = true; | 157 condition = true; |
154 ... | 158 ... |
155 SDL_UnlockMutex(lock); | 159 SDL_UnlockMutex(lock); |
156 */ | 160 */ |
157 int SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms) | 161 int |
158 { | 162 SDL_CondWaitTimeout(SDL_cond * cond, SDL_mutex * mutex, Uint32 ms) |
159 int retval; | 163 { |
160 | 164 int retval; |
161 if ( ! cond ) { | 165 |
162 SDL_SetError("Passed a NULL condition variable"); | 166 if (!cond) { |
163 return -1; | 167 SDL_SetError("Passed a NULL condition variable"); |
164 } | 168 return -1; |
165 | 169 } |
166 /* Obtain the protection mutex, and increment the number of waiters. | 170 |
167 This allows the signal mechanism to only perform a signal if there | 171 /* Obtain the protection mutex, and increment the number of waiters. |
168 are waiting threads. | 172 This allows the signal mechanism to only perform a signal if there |
169 */ | 173 are waiting threads. |
170 SDL_LockMutex(cond->lock); | 174 */ |
171 ++cond->waiting; | 175 SDL_LockMutex(cond->lock); |
172 SDL_UnlockMutex(cond->lock); | 176 ++cond->waiting; |
173 | 177 SDL_UnlockMutex(cond->lock); |
174 /* Unlock the mutex, as is required by condition variable semantics */ | 178 |
175 SDL_UnlockMutex(mutex); | 179 /* Unlock the mutex, as is required by condition variable semantics */ |
176 | 180 SDL_UnlockMutex(mutex); |
177 /* Wait for a signal */ | 181 |
178 if ( ms == SDL_MUTEX_MAXWAIT ) { | 182 /* Wait for a signal */ |
179 retval = SDL_SemWait(cond->wait_sem); | 183 if (ms == SDL_MUTEX_MAXWAIT) { |
180 } else { | 184 retval = SDL_SemWait(cond->wait_sem); |
181 retval = SDL_SemWaitTimeout(cond->wait_sem, ms); | 185 } else { |
182 } | 186 retval = SDL_SemWaitTimeout(cond->wait_sem, ms); |
183 | 187 } |
184 /* Let the signaler know we have completed the wait, otherwise | 188 |
185 the signaler can race ahead and get the condition semaphore | 189 /* Let the signaler know we have completed the wait, otherwise |
186 if we are stopped between the mutex unlock and semaphore wait, | 190 the signaler can race ahead and get the condition semaphore |
187 giving a deadlock. See the following URL for details: | 191 if we are stopped between the mutex unlock and semaphore wait, |
188 http://www-classic.be.com/aboutbe/benewsletter/volume_III/Issue40.html | 192 giving a deadlock. See the following URL for details: |
189 */ | 193 http://www-classic.be.com/aboutbe/benewsletter/volume_III/Issue40.html |
190 SDL_LockMutex(cond->lock); | 194 */ |
191 if ( cond->signals > 0 ) { | 195 SDL_LockMutex(cond->lock); |
192 /* If we timed out, we need to eat a condition signal */ | 196 if (cond->signals > 0) { |
193 if ( retval > 0 ) { | 197 /* If we timed out, we need to eat a condition signal */ |
194 SDL_SemWait(cond->wait_sem); | 198 if (retval > 0) { |
195 } | 199 SDL_SemWait(cond->wait_sem); |
196 /* We always notify the signal thread that we are done */ | 200 } |
197 SDL_SemPost(cond->wait_done); | 201 /* We always notify the signal thread that we are done */ |
198 | 202 SDL_SemPost(cond->wait_done); |
199 /* Signal handshake complete */ | 203 |
200 --cond->signals; | 204 /* Signal handshake complete */ |
201 } | 205 --cond->signals; |
202 --cond->waiting; | 206 } |
203 SDL_UnlockMutex(cond->lock); | 207 --cond->waiting; |
204 | 208 SDL_UnlockMutex(cond->lock); |
205 /* Lock the mutex, as is required by condition variable semantics */ | 209 |
206 SDL_LockMutex(mutex); | 210 /* Lock the mutex, as is required by condition variable semantics */ |
207 | 211 SDL_LockMutex(mutex); |
208 return retval; | 212 |
213 return retval; | |
209 } | 214 } |
210 | 215 |
211 /* Wait on the condition variable forever */ | 216 /* Wait on the condition variable forever */ |
212 int SDL_CondWait(SDL_cond *cond, SDL_mutex *mutex) | 217 int |
213 { | 218 SDL_CondWait(SDL_cond * cond, SDL_mutex * mutex) |
214 return SDL_CondWaitTimeout(cond, mutex, SDL_MUTEX_MAXWAIT); | 219 { |
215 } | 220 return SDL_CondWaitTimeout(cond, mutex, SDL_MUTEX_MAXWAIT); |
221 } | |
222 | |
223 /* vi: set ts=4 sw=4 expandtab: */ |