aboutsummaryrefslogtreecommitdiff
path: root/CPP/Windows/Synchronization.h
diff options
context:
space:
mode:
Diffstat (limited to 'CPP/Windows/Synchronization.h')
-rw-r--r--CPP/Windows/Synchronization.h393
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
16namespace NWindows {
17namespace NSynchronization {
18
19class CBaseEvent MY_UNCOPYABLE
20{
21protected:
22 ::CEvent _object;
23public:
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
54class CManualResetEvent: public CBaseEvent
55{
56public:
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
75class CAutoResetEvent: public CBaseEvent
76{
77public:
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
94class CObject: public CHandle
95{
96public:
97 WRes Lock(DWORD timeoutInterval = INFINITE)
98 { return (::WaitForSingleObject(_handle, timeoutInterval) == WAIT_OBJECT_0 ? 0 : ::GetLastError()); }
99};
100
101class CMutex: public CObject
102{
103public:
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
126class CMutexLock MY_UNCOPYABLE
127{
128 CMutex *_object;
129public:
130 CMutexLock(CMutex &object): _object(&object) { _object->Lock(); }
131 ~CMutexLock() { _object->Release(); }
132};
133
134#endif // _WIN32
135*/
136
137
138class CSemaphore MY_UNCOPYABLE
139{
140 ::CSemaphore _object;
141public:
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
165class CCriticalSection MY_UNCOPYABLE
166{
167 ::CCriticalSection _object;
168public:
169 CCriticalSection() { CriticalSection_Init(&_object); }
170 ~CCriticalSection() { CriticalSection_Delete(&_object); }
171 void Enter() { CriticalSection_Enter(&_object); }
172 void Leave() { CriticalSection_Leave(&_object); }
173};
174
175class CCriticalSectionLock MY_UNCOPYABLE
176{
177 CCriticalSection *_object;
178 void Unlock() { _object->Leave(); }
179public:
180 CCriticalSectionLock(CCriticalSection &object): _object(&object) {_object->Enter(); }
181 ~CCriticalSectionLock() { Unlock(); }
182};
183
184
185#ifdef _WIN32
186
187typedef HANDLE CHandle_WFMO;
188typedef CSemaphore CSemaphore_WFMO;
189typedef CAutoResetEvent CAutoResetEvent_WFMO;
190typedef CManualResetEvent CManualResetEvent_WFMO;
191
192inline 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
211class CSynchro MY_UNCOPYABLE
212{
213 pthread_mutex_t _mutex;
214 pthread_cond_t _cond;
215 bool _isValid;
216
217public:
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
256struct CBaseHandle_WFMO;
257typedef 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
263DWORD WINAPI WaitForMultiObj_Any_Infinite(DWORD count, const CHandle_WFMO *handles);
264
265
266struct 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
277class CBaseEvent_WFMO : public CBaseHandle_WFMO
278{
279 bool _manual_reset;
280 bool _state;
281
282public:
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
325class CManualResetEvent_WFMO: public CBaseEvent_WFMO
326{
327public:
328 WRes Create(CSynchro *sync, bool initiallyOwn = false) { return CBaseEvent_WFMO::Create(sync, true, initiallyOwn); }
329};
330
331
332class CAutoResetEvent_WFMO: public CBaseEvent_WFMO
333{
334public:
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
343class CSemaphore_WFMO : public CBaseHandle_WFMO
344{
345 UInt32 _count;
346 UInt32 _maxCount;
347
348public:
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