diff options
Diffstat (limited to 'CPP/Windows/Synchronization.h')
-rw-r--r-- | CPP/Windows/Synchronization.h | 393 |
1 files changed, 393 insertions, 0 deletions
diff --git a/CPP/Windows/Synchronization.h b/CPP/Windows/Synchronization.h new file mode 100644 index 0000000..7d2e8d2 --- /dev/null +++ b/CPP/Windows/Synchronization.h | |||
@@ -0,0 +1,393 @@ | |||
1 | // Windows/Synchronization.h | ||
2 | |||
3 | #ifndef __WINDOWS_SYNCHRONIZATION_H | ||
4 | #define __WINDOWS_SYNCHRONIZATION_H | ||
5 | |||
6 | #include "../../C/Threads.h" | ||
7 | |||
8 | #include "../Common/MyTypes.h" | ||
9 | |||
10 | #include "Defs.h" | ||
11 | |||
12 | #ifdef _WIN32 | ||
13 | #include "Handle.h" | ||
14 | #endif | ||
15 | |||
16 | namespace NWindows { | ||
17 | namespace NSynchronization { | ||
18 | |||
19 | class CBaseEvent MY_UNCOPYABLE | ||
20 | { | ||
21 | protected: | ||
22 | ::CEvent _object; | ||
23 | public: | ||
24 | bool IsCreated() { return Event_IsCreated(&_object) != 0; } | ||
25 | |||
26 | CBaseEvent() { Event_Construct(&_object); } | ||
27 | ~CBaseEvent() { Close(); } | ||
28 | WRes Close() { return Event_Close(&_object); } | ||
29 | |||
30 | #ifdef _WIN32 | ||
31 | operator HANDLE() { return _object; } | ||
32 | WRes Create(bool manualReset, bool initiallyOwn, LPCTSTR name = NULL, LPSECURITY_ATTRIBUTES sa = NULL) | ||
33 | { | ||
34 | _object = ::CreateEvent(sa, BoolToBOOL(manualReset), BoolToBOOL(initiallyOwn), name); | ||
35 | if (name == NULL && _object != 0) | ||
36 | return 0; | ||
37 | return ::GetLastError(); | ||
38 | } | ||
39 | WRes Open(DWORD desiredAccess, bool inheritHandle, LPCTSTR name) | ||
40 | { | ||
41 | _object = ::OpenEvent(desiredAccess, BoolToBOOL(inheritHandle), name); | ||
42 | if (_object != 0) | ||
43 | return 0; | ||
44 | return ::GetLastError(); | ||
45 | } | ||
46 | #endif | ||
47 | |||
48 | WRes Set() { return Event_Set(&_object); } | ||
49 | // bool Pulse() { return BOOLToBool(::PulseEvent(_handle)); } | ||
50 | WRes Reset() { return Event_Reset(&_object); } | ||
51 | WRes Lock() { return Event_Wait(&_object); } | ||
52 | }; | ||
53 | |||
54 | class CManualResetEvent: public CBaseEvent | ||
55 | { | ||
56 | public: | ||
57 | WRes Create(bool initiallyOwn = false) | ||
58 | { | ||
59 | return ManualResetEvent_Create(&_object, initiallyOwn ? 1: 0); | ||
60 | } | ||
61 | WRes CreateIfNotCreated_Reset() | ||
62 | { | ||
63 | if (IsCreated()) | ||
64 | return Reset(); | ||
65 | return ManualResetEvent_CreateNotSignaled(&_object); | ||
66 | } | ||
67 | #ifdef _WIN32 | ||
68 | WRes CreateWithName(bool initiallyOwn, LPCTSTR name) | ||
69 | { | ||
70 | return CBaseEvent::Create(true, initiallyOwn, name); | ||
71 | } | ||
72 | #endif | ||
73 | }; | ||
74 | |||
75 | class CAutoResetEvent: public CBaseEvent | ||
76 | { | ||
77 | public: | ||
78 | WRes Create() | ||
79 | { | ||
80 | return AutoResetEvent_CreateNotSignaled(&_object); | ||
81 | } | ||
82 | WRes CreateIfNotCreated_Reset() | ||
83 | { | ||
84 | if (IsCreated()) | ||
85 | return Reset(); | ||
86 | return AutoResetEvent_CreateNotSignaled(&_object); | ||
87 | } | ||
88 | }; | ||
89 | |||
90 | |||
91 | /* | ||
92 | #ifdef _WIN32 | ||
93 | |||
94 | class CObject: public CHandle | ||
95 | { | ||
96 | public: | ||
97 | WRes Lock(DWORD timeoutInterval = INFINITE) | ||
98 | { return (::WaitForSingleObject(_handle, timeoutInterval) == WAIT_OBJECT_0 ? 0 : ::GetLastError()); } | ||
99 | }; | ||
100 | |||
101 | class CMutex: public CObject | ||
102 | { | ||
103 | public: | ||
104 | WRes Create(bool initiallyOwn, LPCTSTR name = NULL, LPSECURITY_ATTRIBUTES sa = NULL) | ||
105 | { | ||
106 | _handle = ::CreateMutex(sa, BoolToBOOL(initiallyOwn), name); | ||
107 | if (name == NULL && _handle != 0) | ||
108 | return 0; | ||
109 | return ::GetLastError(); | ||
110 | } | ||
111 | #ifndef UNDER_CE | ||
112 | WRes Open(DWORD desiredAccess, bool inheritHandle, LPCTSTR name) | ||
113 | { | ||
114 | _handle = ::OpenMutex(desiredAccess, BoolToBOOL(inheritHandle), name); | ||
115 | if (_handle != 0) | ||
116 | return 0; | ||
117 | return ::GetLastError(); | ||
118 | } | ||
119 | #endif | ||
120 | WRes Release() | ||
121 | { | ||
122 | return ::ReleaseMutex(_handle) ? 0 : ::GetLastError(); | ||
123 | } | ||
124 | }; | ||
125 | |||
126 | class CMutexLock MY_UNCOPYABLE | ||
127 | { | ||
128 | CMutex *_object; | ||
129 | public: | ||
130 | CMutexLock(CMutex &object): _object(&object) { _object->Lock(); } | ||
131 | ~CMutexLock() { _object->Release(); } | ||
132 | }; | ||
133 | |||
134 | #endif // _WIN32 | ||
135 | */ | ||
136 | |||
137 | |||
138 | class CSemaphore MY_UNCOPYABLE | ||
139 | { | ||
140 | ::CSemaphore _object; | ||
141 | public: | ||
142 | CSemaphore() { Semaphore_Construct(&_object); } | ||
143 | ~CSemaphore() { Close(); } | ||
144 | WRes Close() { return Semaphore_Close(&_object); } | ||
145 | |||
146 | #ifdef _WIN32 | ||
147 | operator HANDLE() { return _object; } | ||
148 | #endif | ||
149 | |||
150 | // bool IsCreated() const { return Semaphore_IsCreated(&_object) != 0; } | ||
151 | |||
152 | WRes Create(UInt32 initCount, UInt32 maxCount) | ||
153 | { | ||
154 | return Semaphore_Create(&_object, initCount, maxCount); | ||
155 | } | ||
156 | WRes OptCreateInit(UInt32 initCount, UInt32 maxCount) | ||
157 | { | ||
158 | return Semaphore_OptCreateInit(&_object, initCount, maxCount); | ||
159 | } | ||
160 | WRes Release() { return Semaphore_Release1(&_object); } | ||
161 | WRes Release(UInt32 releaseCount) { return Semaphore_ReleaseN(&_object, releaseCount); } | ||
162 | WRes Lock() { return Semaphore_Wait(&_object); } | ||
163 | }; | ||
164 | |||
165 | class CCriticalSection MY_UNCOPYABLE | ||
166 | { | ||
167 | ::CCriticalSection _object; | ||
168 | public: | ||
169 | CCriticalSection() { CriticalSection_Init(&_object); } | ||
170 | ~CCriticalSection() { CriticalSection_Delete(&_object); } | ||
171 | void Enter() { CriticalSection_Enter(&_object); } | ||
172 | void Leave() { CriticalSection_Leave(&_object); } | ||
173 | }; | ||
174 | |||
175 | class CCriticalSectionLock MY_UNCOPYABLE | ||
176 | { | ||
177 | CCriticalSection *_object; | ||
178 | void Unlock() { _object->Leave(); } | ||
179 | public: | ||
180 | CCriticalSectionLock(CCriticalSection &object): _object(&object) {_object->Enter(); } | ||
181 | ~CCriticalSectionLock() { Unlock(); } | ||
182 | }; | ||
183 | |||
184 | |||
185 | #ifdef _WIN32 | ||
186 | |||
187 | typedef HANDLE CHandle_WFMO; | ||
188 | typedef CSemaphore CSemaphore_WFMO; | ||
189 | typedef CAutoResetEvent CAutoResetEvent_WFMO; | ||
190 | typedef CManualResetEvent CManualResetEvent_WFMO; | ||
191 | |||
192 | inline DWORD WINAPI WaitForMultiObj_Any_Infinite(DWORD count, const CHandle_WFMO *handles) | ||
193 | { | ||
194 | return ::WaitForMultipleObjects(count, handles, FALSE, INFINITE); | ||
195 | } | ||
196 | |||
197 | #define SYNC_OBJ_DECL(obj) | ||
198 | #define SYNC_WFMO(x) | ||
199 | #define SYNC_PARAM(x) | ||
200 | #define SYNC_PARAM_DECL(x) | ||
201 | |||
202 | #else // _WIN32 | ||
203 | |||
204 | // POSIX sync objects for WaitForMultipleObjects | ||
205 | |||
206 | #define SYNC_WFMO(x) x | ||
207 | #define SYNC_PARAM(x) x, | ||
208 | #define SYNC_PARAM_DECL(x) NWindows::NSynchronization::CSynchro *x | ||
209 | #define SYNC_OBJ_DECL(x) NWindows::NSynchronization::CSynchro x; | ||
210 | |||
211 | class CSynchro MY_UNCOPYABLE | ||
212 | { | ||
213 | pthread_mutex_t _mutex; | ||
214 | pthread_cond_t _cond; | ||
215 | bool _isValid; | ||
216 | |||
217 | public: | ||
218 | CSynchro() { _isValid = false; } | ||
219 | ~CSynchro() | ||
220 | { | ||
221 | if (_isValid) | ||
222 | { | ||
223 | ::pthread_mutex_destroy(&_mutex); | ||
224 | ::pthread_cond_destroy(&_cond); | ||
225 | } | ||
226 | _isValid = false; | ||
227 | } | ||
228 | WRes Create() | ||
229 | { | ||
230 | RINOK(::pthread_mutex_init(&_mutex, 0)); | ||
231 | WRes ret = ::pthread_cond_init(&_cond, 0); | ||
232 | _isValid = 1; | ||
233 | return ret; | ||
234 | } | ||
235 | WRes Enter() | ||
236 | { | ||
237 | return ::pthread_mutex_lock(&_mutex); | ||
238 | } | ||
239 | WRes Leave() | ||
240 | { | ||
241 | return ::pthread_mutex_unlock(&_mutex); | ||
242 | } | ||
243 | WRes WaitCond() | ||
244 | { | ||
245 | return ::pthread_cond_wait(&_cond, &_mutex); | ||
246 | } | ||
247 | WRes LeaveAndSignal() | ||
248 | { | ||
249 | WRes res1 = ::pthread_cond_broadcast(&_cond); | ||
250 | WRes res2 = ::pthread_mutex_unlock(&_mutex); | ||
251 | return (res2 ? res2 : res1); | ||
252 | } | ||
253 | }; | ||
254 | |||
255 | |||
256 | struct CBaseHandle_WFMO; | ||
257 | typedef NWindows::NSynchronization::CBaseHandle_WFMO *CHandle_WFMO; | ||
258 | |||
259 | // these constants are from Windows | ||
260 | #define WAIT_OBJECT_0 0 | ||
261 | #define WAIT_FAILED ((DWORD)0xFFFFFFFF) | ||
262 | |||
263 | DWORD WINAPI WaitForMultiObj_Any_Infinite(DWORD count, const CHandle_WFMO *handles); | ||
264 | |||
265 | |||
266 | struct CBaseHandle_WFMO MY_UNCOPYABLE | ||
267 | { | ||
268 | CSynchro *_sync; | ||
269 | |||
270 | CBaseHandle_WFMO(): _sync(NULL) {} | ||
271 | |||
272 | operator CHandle_WFMO() { return this; } | ||
273 | virtual bool IsSignaledAndUpdate() = 0; | ||
274 | }; | ||
275 | |||
276 | |||
277 | class CBaseEvent_WFMO : public CBaseHandle_WFMO | ||
278 | { | ||
279 | bool _manual_reset; | ||
280 | bool _state; | ||
281 | |||
282 | public: | ||
283 | |||
284 | // bool IsCreated() { return (this->_sync != NULL); } | ||
285 | // CBaseEvent_WFMO() { ; } | ||
286 | ~CBaseEvent_WFMO() { Close(); } | ||
287 | |||
288 | WRes Close() { this->_sync = NULL; return 0; } | ||
289 | |||
290 | WRes Create( | ||
291 | CSynchro *sync, | ||
292 | bool manualReset, bool initiallyOwn) | ||
293 | { | ||
294 | this->_sync = sync; | ||
295 | this->_manual_reset = manualReset; | ||
296 | this->_state = initiallyOwn; | ||
297 | return 0; | ||
298 | } | ||
299 | |||
300 | WRes Set() | ||
301 | { | ||
302 | RINOK(this->_sync->Enter()); | ||
303 | this->_state = true; | ||
304 | return this->_sync->LeaveAndSignal(); | ||
305 | } | ||
306 | |||
307 | WRes Reset() | ||
308 | { | ||
309 | RINOK(this->_sync->Enter()); | ||
310 | this->_state = false; | ||
311 | return this->_sync->Leave(); | ||
312 | } | ||
313 | |||
314 | virtual bool IsSignaledAndUpdate() | ||
315 | { | ||
316 | if (this->_state == false) | ||
317 | return false; | ||
318 | if (this->_manual_reset == false) | ||
319 | this->_state = false; | ||
320 | return true; | ||
321 | } | ||
322 | }; | ||
323 | |||
324 | |||
325 | class CManualResetEvent_WFMO: public CBaseEvent_WFMO | ||
326 | { | ||
327 | public: | ||
328 | WRes Create(CSynchro *sync, bool initiallyOwn = false) { return CBaseEvent_WFMO::Create(sync, true, initiallyOwn); } | ||
329 | }; | ||
330 | |||
331 | |||
332 | class CAutoResetEvent_WFMO: public CBaseEvent_WFMO | ||
333 | { | ||
334 | public: | ||
335 | WRes Create(CSynchro *sync) { return CBaseEvent_WFMO::Create(sync, false, false); } | ||
336 | WRes CreateIfNotCreated_Reset(CSynchro *sync) | ||
337 | { | ||
338 | return Create(sync); | ||
339 | } | ||
340 | }; | ||
341 | |||
342 | |||
343 | class CSemaphore_WFMO : public CBaseHandle_WFMO | ||
344 | { | ||
345 | UInt32 _count; | ||
346 | UInt32 _maxCount; | ||
347 | |||
348 | public: | ||
349 | CSemaphore_WFMO() : _count(0), _maxCount(0) {} | ||
350 | |||
351 | WRes Close() { this->_sync = NULL; return 0; } | ||
352 | |||
353 | WRes Create(CSynchro *sync, UInt32 initCount, UInt32 maxCount) | ||
354 | { | ||
355 | if (initCount > maxCount || maxCount < 1) | ||
356 | return EINVAL; | ||
357 | this->_sync = sync; | ||
358 | this->_count = initCount; | ||
359 | this->_maxCount = maxCount; | ||
360 | return 0; | ||
361 | } | ||
362 | |||
363 | WRes Release(UInt32 releaseCount = 1) | ||
364 | { | ||
365 | if (releaseCount < 1) | ||
366 | return EINVAL; | ||
367 | |||
368 | RINOK(this->_sync->Enter()); | ||
369 | UInt32 newCount = this->_count + releaseCount; | ||
370 | if (newCount > this->_maxCount) | ||
371 | { | ||
372 | RINOK(this->_sync->Leave()); | ||
373 | return ERROR_TOO_MANY_POSTS; // EINVAL | ||
374 | } | ||
375 | this->_count = newCount; | ||
376 | |||
377 | return this->_sync->LeaveAndSignal(); | ||
378 | } | ||
379 | |||
380 | virtual bool IsSignaledAndUpdate() | ||
381 | { | ||
382 | if (this->_count == 0) | ||
383 | return false; | ||
384 | this->_count--; | ||
385 | return true; | ||
386 | } | ||
387 | }; | ||
388 | |||
389 | #endif // _WIN32 | ||
390 | |||
391 | }} | ||
392 | |||
393 | #endif | ||