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: */