Mercurial > sdl-ios-xcode
comparison src/thread/win32/win_ce_semaphore.c @ 1662:782fd950bd46 SDL-1.3
Revamp of the video system in progress - adding support for multiple displays, multiple windows, and a full video mode selection API.
WARNING: None of the video drivers have been updated for the new API yet! The API is still under design and very fluid.
The code is now run through a consistent indent format:
indent -i4 -nut -nsc -br -ce
The headers are being converted to automatically generate doxygen documentation.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Sun, 28 May 2006 13:04:16 +0000 |
parents | bb6839704ed6 |
children | 4da1ee79c9af |
comparison
equal
deleted
inserted
replaced
1661:281d3f4870e5 | 1662:782fd950bd46 |
---|---|
33 | 33 |
34 #include "win_ce_semaphore.h" | 34 #include "win_ce_semaphore.h" |
35 | 35 |
36 static SYNCHHANDLE CleanUp (SYNCHHANDLE hSynch, DWORD Flags); | 36 static SYNCHHANDLE CleanUp (SYNCHHANDLE hSynch, DWORD Flags); |
37 | 37 |
38 SYNCHHANDLE CreateSemaphoreCE ( | 38 SYNCHHANDLE |
39 | 39 CreateSemaphoreCE (LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, /* pointer to security attributes */ |
40 LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, /* pointer to security attributes */ | 40 LONG lInitialCount, /* initial count */ |
41 LONG lInitialCount, /* initial count */ | 41 LONG lMaximumCount, /* maximum count */ |
42 LONG lMaximumCount, /* maximum count */ | 42 LPCTSTR lpName) |
43 LPCTSTR lpName ) | |
44 | |
45 /* Semaphore for use with Windows CE that does not support them directly. | 43 /* Semaphore for use with Windows CE that does not support them directly. |
46 Requires a counter, a mutex to protect the counter, and an | 44 Requires a counter, a mutex to protect the counter, and an |
47 autoreset event. | 45 autoreset event. |
48 | 46 |
49 Here are the rules that must always hold between the autoreset event | 47 Here are the rules that must always hold between the autoreset event |
55 BUT, a thread can wait on the event without owning the mutex | 53 BUT, a thread can wait on the event without owning the mutex |
56 (this is clearly necessary or else the event could never be set). | 54 (this is clearly necessary or else the event could never be set). |
57 2. The event is in a signaled state if and only if the current semaphore | 55 2. The event is in a signaled state if and only if the current semaphore |
58 count ("CurCount") is greater than zero. | 56 count ("CurCount") is greater than zero. |
59 3. The semaphore count is always >= 0 and <= the maximum count */ | 57 3. The semaphore count is always >= 0 and <= the maximum count */ |
60 | 58 { |
61 { | 59 SYNCHHANDLE hSynch = NULL, result = NULL; |
62 SYNCHHANDLE hSynch = NULL, result = NULL; | 60 |
63 | 61 __try { |
64 __try | 62 if (lInitialCount > lMaximumCount || lMaximumCount < 0 |
65 { | 63 || lInitialCount < 0) { |
66 if (lInitialCount > lMaximumCount || lMaximumCount < 0 || lInitialCount < 0) | 64 /* Bad parameters */ |
67 { | 65 SetLastError (SYNCH_ERROR); |
68 /* Bad parameters */ | 66 __leave; |
69 SetLastError (SYNCH_ERROR); | 67 } |
70 __leave; | 68 |
71 } | 69 hSynch = |
72 | 70 HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, |
73 hSynch = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, SYNCH_HANDLE_SIZE); | 71 SYNCH_HANDLE_SIZE); |
74 if (hSynch == NULL) __leave; | 72 if (hSynch == NULL) |
75 | 73 __leave; |
76 hSynch->MaxCount = lMaximumCount; | 74 |
77 hSynch->CurCount = lInitialCount; | 75 hSynch->MaxCount = lMaximumCount; |
78 hSynch->lpName = lpName; | 76 hSynch->CurCount = lInitialCount; |
79 | 77 hSynch->lpName = lpName; |
80 hSynch->hMutex = CreateMutex (lpSemaphoreAttributes, FALSE, NULL); | 78 |
81 | 79 hSynch->hMutex = CreateMutex (lpSemaphoreAttributes, FALSE, NULL); |
82 WaitForSingleObject (hSynch->hMutex, INFINITE); | 80 |
83 /* Create the event. It is initially signaled if and only if the | 81 WaitForSingleObject (hSynch->hMutex, INFINITE); |
84 initial count is > 0 */ | 82 /* Create the event. It is initially signaled if and only if the |
85 hSynch->hEvent = CreateEvent (lpSemaphoreAttributes, FALSE, | 83 initial count is > 0 */ |
86 lInitialCount > 0, NULL); | 84 hSynch->hEvent = CreateEvent (lpSemaphoreAttributes, FALSE, |
87 ReleaseMutex (hSynch->hMutex); | 85 lInitialCount > 0, NULL); |
88 hSynch->hSemph = NULL; | 86 ReleaseMutex (hSynch->hMutex); |
89 } | 87 hSynch->hSemph = NULL; |
90 __finally | 88 } |
91 { | 89 __finally { |
92 /* Return with the handle, or, if there was any error, return | 90 /* Return with the handle, or, if there was any error, return |
93 a null after closing any open handles and freeing any allocated memory. */ | 91 a null after closing any open handles and freeing any allocated memory. */ |
94 result=CleanUp(hSynch, 6 /* An event and a mutex, but no semaphore. */); | 92 result = |
95 } | 93 CleanUp (hSynch, |
96 | 94 6 /* An event and a mutex, but no semaphore. */ ); |
97 return result; | 95 } |
98 } | 96 |
99 | 97 return result; |
100 BOOL ReleaseSemaphoreCE (SYNCHHANDLE hSemCE, LONG cReleaseCount, LPLONG lpPreviousCount) | 98 } |
99 | |
100 BOOL | |
101 ReleaseSemaphoreCE (SYNCHHANDLE hSemCE, LONG cReleaseCount, | |
102 LPLONG lpPreviousCount) | |
101 /* Windows CE equivalent to ReleaseSemaphore. */ | 103 /* Windows CE equivalent to ReleaseSemaphore. */ |
102 { | 104 { |
103 BOOL Result = TRUE; | 105 BOOL Result = TRUE; |
104 | 106 |
105 /* Gain access to the object to assure that the release count | 107 /* Gain access to the object to assure that the release count |
106 would not cause the total count to exceed the maximum. */ | 108 would not cause the total count to exceed the maximum. */ |
107 | 109 |
108 __try | 110 __try { |
109 { | 111 WaitForSingleObject (hSemCE->hMutex, INFINITE); |
110 WaitForSingleObject (hSemCE->hMutex, INFINITE); | 112 /* reply only if asked to */ |
111 /* reply only if asked to */ | 113 if (lpPreviousCount != NULL) |
112 if (lpPreviousCount!=NULL) | 114 *lpPreviousCount = hSemCE->CurCount; |
113 *lpPreviousCount = hSemCE->CurCount; | 115 if (hSemCE->CurCount + cReleaseCount > hSemCE->MaxCount |
114 if (hSemCE->CurCount + cReleaseCount > hSemCE->MaxCount || cReleaseCount <= 0) | 116 || cReleaseCount <= 0) { |
115 { | 117 SetLastError (SYNCH_ERROR); |
116 SetLastError (SYNCH_ERROR); | 118 Result = FALSE; |
117 Result = FALSE; | 119 __leave; |
118 __leave; | 120 } |
119 } | 121 hSemCE->CurCount += cReleaseCount; |
120 hSemCE->CurCount += cReleaseCount; | 122 |
121 | 123 /* Set the autoreset event, releasing exactly one waiting thread, now or |
122 /* Set the autoreset event, releasing exactly one waiting thread, now or | 124 in the future. */ |
123 in the future. */ | 125 |
124 | 126 SetEvent (hSemCE->hEvent); |
125 SetEvent (hSemCE->hEvent); | 127 } |
126 } | 128 __finally { |
127 __finally | 129 ReleaseMutex (hSemCE->hMutex); |
128 { | 130 } |
129 ReleaseMutex (hSemCE->hMutex); | 131 |
130 } | 132 return Result; |
131 | 133 } |
132 return Result; | 134 |
133 } | 135 DWORD |
134 | 136 WaitForSemaphoreCE (SYNCHHANDLE hSemCE, DWORD dwMilliseconds) |
135 DWORD WaitForSemaphoreCE (SYNCHHANDLE hSemCE, DWORD dwMilliseconds) | |
136 /* Windows CE semaphore equivalent of WaitForSingleObject. */ | 137 /* Windows CE semaphore equivalent of WaitForSingleObject. */ |
137 { | 138 { |
138 DWORD WaitResult; | 139 DWORD WaitResult; |
139 | 140 |
140 WaitResult = WaitForSingleObject (hSemCE->hMutex, dwMilliseconds); | 141 WaitResult = WaitForSingleObject (hSemCE->hMutex, dwMilliseconds); |
141 if (WaitResult != WAIT_OBJECT_0 && WaitResult != WAIT_ABANDONED_0) return WaitResult; | 142 if (WaitResult != WAIT_OBJECT_0 && WaitResult != WAIT_ABANDONED_0) |
142 while (hSemCE->CurCount <= 0) | 143 return WaitResult; |
143 { | 144 while (hSemCE->CurCount <= 0) { |
144 | 145 |
145 /* The count is 0, and the thread must wait on the event (which, by | 146 /* The count is 0, and the thread must wait on the event (which, by |
146 the rules, is currently reset) for semaphore resources to become | 147 the rules, is currently reset) for semaphore resources to become |
147 available. First, of course, the mutex must be released so that another | 148 available. First, of course, the mutex must be released so that another |
148 thread will be capable of setting the event. */ | 149 thread will be capable of setting the event. */ |
149 | 150 |
150 ReleaseMutex (hSemCE->hMutex); | 151 ReleaseMutex (hSemCE->hMutex); |
151 | 152 |
152 /* Wait for the event to be signaled, indicating a semaphore state change. | 153 /* Wait for the event to be signaled, indicating a semaphore state change. |
153 The event is autoreset and signaled with a SetEvent (not PulseEvent) | 154 The event is autoreset and signaled with a SetEvent (not PulseEvent) |
154 so exactly one waiting thread (whether or not there is currently | 155 so exactly one waiting thread (whether or not there is currently |
155 a waiting thread) is released as a result of the SetEvent. */ | 156 a waiting thread) is released as a result of the SetEvent. */ |
156 | 157 |
157 WaitResult = WaitForSingleObject (hSemCE->hEvent, dwMilliseconds); | 158 WaitResult = WaitForSingleObject (hSemCE->hEvent, dwMilliseconds); |
158 if (WaitResult != WAIT_OBJECT_0) return WaitResult; | 159 if (WaitResult != WAIT_OBJECT_0) |
159 | 160 return WaitResult; |
160 /* This is where the properties of setting of an autoreset event is critical | 161 |
161 to assure that, even if the semaphore state changes between the | 162 /* This is where the properties of setting of an autoreset event is critical |
162 preceding Wait and the next, and even if NO threads are waiting | 163 to assure that, even if the semaphore state changes between the |
163 on the event at the time of the SetEvent, at least one thread | 164 preceding Wait and the next, and even if NO threads are waiting |
164 will be released. | 165 on the event at the time of the SetEvent, at least one thread |
165 Pulsing a manual reset event would appear to work, but it would have | 166 will be released. |
166 a defect which could appear if the semaphore state changed between | 167 Pulsing a manual reset event would appear to work, but it would have |
167 the two waits. */ | 168 a defect which could appear if the semaphore state changed between |
168 | 169 the two waits. */ |
169 WaitResult = WaitForSingleObject (hSemCE->hMutex, dwMilliseconds); | 170 |
170 if (WaitResult != WAIT_OBJECT_0 && WaitResult != WAIT_ABANDONED_0) return WaitResult; | 171 WaitResult = WaitForSingleObject (hSemCE->hMutex, dwMilliseconds); |
171 | 172 if (WaitResult != WAIT_OBJECT_0 && WaitResult != WAIT_ABANDONED_0) |
172 } | 173 return WaitResult; |
173 /* The count is not zero and this thread owns the mutex. */ | 174 |
174 | 175 } |
175 hSemCE->CurCount--; | 176 /* The count is not zero and this thread owns the mutex. */ |
176 /* The event is now unsignaled, BUT, the semaphore count may not be | 177 |
177 zero, in which case the event should be signaled again | 178 hSemCE->CurCount--; |
178 before releasing the mutex. */ | 179 /* The event is now unsignaled, BUT, the semaphore count may not be |
179 | 180 zero, in which case the event should be signaled again |
180 if (hSemCE->CurCount > 0) SetEvent (hSemCE->hEvent); | 181 before releasing the mutex. */ |
181 ReleaseMutex (hSemCE->hMutex); | 182 |
182 return WaitResult; | 183 if (hSemCE->CurCount > 0) |
183 } | 184 SetEvent (hSemCE->hEvent); |
184 | 185 ReleaseMutex (hSemCE->hMutex); |
185 BOOL CloseSynchHandle (SYNCHHANDLE hSynch) | 186 return WaitResult; |
187 } | |
188 | |
189 BOOL | |
190 CloseSynchHandle (SYNCHHANDLE hSynch) | |
186 /* Close a synchronization handle. | 191 /* Close a synchronization handle. |
187 Improvement: Test for a valid handle before dereferencing the handle. */ | 192 Improvement: Test for a valid handle before dereferencing the handle. */ |
188 { | 193 { |
189 BOOL Result = TRUE; | 194 BOOL Result = TRUE; |
190 if (hSynch->hEvent != NULL) Result = Result && CloseHandle (hSynch->hEvent); | 195 if (hSynch->hEvent != NULL) |
191 if (hSynch->hMutex != NULL) Result = Result && CloseHandle (hSynch->hMutex); | 196 Result = Result && CloseHandle (hSynch->hEvent); |
192 if (hSynch->hSemph != NULL) Result = Result && CloseHandle (hSynch->hSemph); | 197 if (hSynch->hMutex != NULL) |
193 HeapFree (GetProcessHeap (), 0, hSynch); | 198 Result = Result && CloseHandle (hSynch->hMutex); |
194 return (Result); | 199 if (hSynch->hSemph != NULL) |
195 } | 200 Result = Result && CloseHandle (hSynch->hSemph); |
196 | 201 HeapFree (GetProcessHeap (), 0, hSynch); |
197 static SYNCHHANDLE CleanUp (SYNCHHANDLE hSynch, DWORD Flags) | 202 return (Result); |
198 { /* Prepare to return from a create of a synchronization handle. | 203 } |
199 If there was any failure, free any allocated resources. | 204 |
200 "Flags" indicates which Win32 objects are required in the | 205 static SYNCHHANDLE |
201 synchronization handle. */ | 206 CleanUp (SYNCHHANDLE hSynch, DWORD Flags) |
202 | 207 { /* Prepare to return from a create of a synchronization handle. |
203 BOOL ok = TRUE; | 208 If there was any failure, free any allocated resources. |
204 | 209 "Flags" indicates which Win32 objects are required in the |
205 if (hSynch == NULL) return NULL; | 210 synchronization handle. */ |
206 if ((Flags & 4) == 1 && (hSynch->hEvent == NULL)) ok = FALSE; | 211 |
207 if ((Flags & 2) == 1 && (hSynch->hMutex == NULL)) ok = FALSE; | 212 BOOL ok = TRUE; |
208 if ((Flags & 1) == 1 && (hSynch->hEvent == NULL)) ok = FALSE; | 213 |
209 if (!ok) | 214 if (hSynch == NULL) |
210 { | 215 return NULL; |
211 CloseSynchHandle (hSynch); | 216 if ((Flags & 4) == 1 && (hSynch->hEvent == NULL)) |
212 return NULL; | 217 ok = FALSE; |
213 } | 218 if ((Flags & 2) == 1 && (hSynch->hMutex == NULL)) |
214 /* Everything worked */ | 219 ok = FALSE; |
215 return hSynch; | 220 if ((Flags & 1) == 1 && (hSynch->hEvent == NULL)) |
216 } | 221 ok = FALSE; |
222 if (!ok) { | |
223 CloseSynchHandle (hSynch); | |
224 return NULL; | |
225 } | |
226 /* Everything worked */ | |
227 return hSynch; | |
228 } | |
229 | |
230 /* vi: set ts=4 sw=4 expandtab: */ |