1370b324cSopenharmony_ci// Windows/Synchronization.h
2370b324cSopenharmony_ci
3370b324cSopenharmony_ci#ifndef ZIP7_INC_WINDOWS_SYNCHRONIZATION_H
4370b324cSopenharmony_ci#define ZIP7_INC_WINDOWS_SYNCHRONIZATION_H
5370b324cSopenharmony_ci
6370b324cSopenharmony_ci#include "../../C/Threads.h"
7370b324cSopenharmony_ci
8370b324cSopenharmony_ci#include "../Common/MyTypes.h"
9370b324cSopenharmony_ci
10370b324cSopenharmony_ci#include "Defs.h"
11370b324cSopenharmony_ci
12370b324cSopenharmony_ci#ifdef _WIN32
13370b324cSopenharmony_ci#include "Handle.h"
14370b324cSopenharmony_ci#endif
15370b324cSopenharmony_ci
16370b324cSopenharmony_cinamespace NWindows {
17370b324cSopenharmony_cinamespace NSynchronization {
18370b324cSopenharmony_ci
19370b324cSopenharmony_ciclass CBaseEvent  MY_UNCOPYABLE
20370b324cSopenharmony_ci{
21370b324cSopenharmony_ciprotected:
22370b324cSopenharmony_ci  ::CEvent _object;
23370b324cSopenharmony_cipublic:
24370b324cSopenharmony_ci  bool IsCreated() { return Event_IsCreated(&_object) != 0; }
25370b324cSopenharmony_ci
26370b324cSopenharmony_ci  CBaseEvent() { Event_Construct(&_object); }
27370b324cSopenharmony_ci  ~CBaseEvent() { Close(); }
28370b324cSopenharmony_ci  WRes Close() { return Event_Close(&_object); }
29370b324cSopenharmony_ci
30370b324cSopenharmony_ci  #ifdef _WIN32
31370b324cSopenharmony_ci  operator HANDLE() { return _object; }
32370b324cSopenharmony_ci  WRes Create(bool manualReset, bool initiallyOwn, LPCTSTR name = NULL, LPSECURITY_ATTRIBUTES sa = NULL)
33370b324cSopenharmony_ci  {
34370b324cSopenharmony_ci    _object = ::CreateEvent(sa, BoolToBOOL(manualReset), BoolToBOOL(initiallyOwn), name);
35370b324cSopenharmony_ci    if (name == NULL && _object != NULL)
36370b324cSopenharmony_ci      return 0;
37370b324cSopenharmony_ci    return ::GetLastError();
38370b324cSopenharmony_ci  }
39370b324cSopenharmony_ci  WRes Open(DWORD desiredAccess, bool inheritHandle, LPCTSTR name)
40370b324cSopenharmony_ci  {
41370b324cSopenharmony_ci    _object = ::OpenEvent(desiredAccess, BoolToBOOL(inheritHandle), name);
42370b324cSopenharmony_ci    if (_object != NULL)
43370b324cSopenharmony_ci      return 0;
44370b324cSopenharmony_ci    return ::GetLastError();
45370b324cSopenharmony_ci  }
46370b324cSopenharmony_ci  #endif
47370b324cSopenharmony_ci
48370b324cSopenharmony_ci  WRes Set() { return Event_Set(&_object); }
49370b324cSopenharmony_ci  // bool Pulse() { return BOOLToBool(::PulseEvent(_handle)); }
50370b324cSopenharmony_ci  WRes Reset() { return Event_Reset(&_object); }
51370b324cSopenharmony_ci  WRes Lock() { return Event_Wait(&_object); }
52370b324cSopenharmony_ci};
53370b324cSopenharmony_ci
54370b324cSopenharmony_ciclass CManualResetEvent: public CBaseEvent
55370b324cSopenharmony_ci{
56370b324cSopenharmony_cipublic:
57370b324cSopenharmony_ci  WRes Create(bool initiallyOwn = false)
58370b324cSopenharmony_ci  {
59370b324cSopenharmony_ci    return ManualResetEvent_Create(&_object, initiallyOwn ? 1: 0);
60370b324cSopenharmony_ci  }
61370b324cSopenharmony_ci  WRes CreateIfNotCreated_Reset()
62370b324cSopenharmony_ci  {
63370b324cSopenharmony_ci    if (IsCreated())
64370b324cSopenharmony_ci      return Reset();
65370b324cSopenharmony_ci    return ManualResetEvent_CreateNotSignaled(&_object);
66370b324cSopenharmony_ci  }
67370b324cSopenharmony_ci  #ifdef _WIN32
68370b324cSopenharmony_ci  WRes CreateWithName(bool initiallyOwn, LPCTSTR name)
69370b324cSopenharmony_ci  {
70370b324cSopenharmony_ci    return CBaseEvent::Create(true, initiallyOwn, name);
71370b324cSopenharmony_ci  }
72370b324cSopenharmony_ci  #endif
73370b324cSopenharmony_ci};
74370b324cSopenharmony_ci
75370b324cSopenharmony_ciclass CAutoResetEvent: public CBaseEvent
76370b324cSopenharmony_ci{
77370b324cSopenharmony_cipublic:
78370b324cSopenharmony_ci  WRes Create()
79370b324cSopenharmony_ci  {
80370b324cSopenharmony_ci    return AutoResetEvent_CreateNotSignaled(&_object);
81370b324cSopenharmony_ci  }
82370b324cSopenharmony_ci  WRes CreateIfNotCreated_Reset()
83370b324cSopenharmony_ci  {
84370b324cSopenharmony_ci    if (IsCreated())
85370b324cSopenharmony_ci      return Reset();
86370b324cSopenharmony_ci    return AutoResetEvent_CreateNotSignaled(&_object);
87370b324cSopenharmony_ci  }
88370b324cSopenharmony_ci};
89370b324cSopenharmony_ci
90370b324cSopenharmony_ci
91370b324cSopenharmony_ci/*
92370b324cSopenharmony_ci#ifdef _WIN32
93370b324cSopenharmony_ci
94370b324cSopenharmony_ciclass CObject: public CHandle
95370b324cSopenharmony_ci{
96370b324cSopenharmony_cipublic:
97370b324cSopenharmony_ci  WRes Lock(DWORD timeoutInterval = INFINITE)
98370b324cSopenharmony_ci    { return (::WaitForSingleObject(_handle, timeoutInterval) == WAIT_OBJECT_0 ? 0 : ::GetLastError()); }
99370b324cSopenharmony_ci};
100370b324cSopenharmony_ci
101370b324cSopenharmony_ciclass CMutex: public CObject
102370b324cSopenharmony_ci{
103370b324cSopenharmony_cipublic:
104370b324cSopenharmony_ci  WRes Create(bool initiallyOwn, LPCTSTR name = NULL, LPSECURITY_ATTRIBUTES sa = NULL)
105370b324cSopenharmony_ci  {
106370b324cSopenharmony_ci    _handle = ::CreateMutex(sa, BoolToBOOL(initiallyOwn), name);
107370b324cSopenharmony_ci    if (name == NULL && _handle != 0)
108370b324cSopenharmony_ci      return 0;
109370b324cSopenharmony_ci    return ::GetLastError();
110370b324cSopenharmony_ci  }
111370b324cSopenharmony_ci  #ifndef UNDER_CE
112370b324cSopenharmony_ci  WRes Open(DWORD desiredAccess, bool inheritHandle, LPCTSTR name)
113370b324cSopenharmony_ci  {
114370b324cSopenharmony_ci    _handle = ::OpenMutex(desiredAccess, BoolToBOOL(inheritHandle), name);
115370b324cSopenharmony_ci    if (_handle != 0)
116370b324cSopenharmony_ci      return 0;
117370b324cSopenharmony_ci    return ::GetLastError();
118370b324cSopenharmony_ci  }
119370b324cSopenharmony_ci  #endif
120370b324cSopenharmony_ci  WRes Release()
121370b324cSopenharmony_ci  {
122370b324cSopenharmony_ci    return ::ReleaseMutex(_handle) ? 0 : ::GetLastError();
123370b324cSopenharmony_ci  }
124370b324cSopenharmony_ci};
125370b324cSopenharmony_ci
126370b324cSopenharmony_ciclass CMutexLock  MY_UNCOPYABLE
127370b324cSopenharmony_ci{
128370b324cSopenharmony_ci  CMutex *_object;
129370b324cSopenharmony_cipublic:
130370b324cSopenharmony_ci  CMutexLock(CMutex &object): _object(&object) { _object->Lock(); }
131370b324cSopenharmony_ci  ~CMutexLock() { _object->Release(); }
132370b324cSopenharmony_ci};
133370b324cSopenharmony_ci
134370b324cSopenharmony_ci#endif // _WIN32
135370b324cSopenharmony_ci*/
136370b324cSopenharmony_ci
137370b324cSopenharmony_ci
138370b324cSopenharmony_ciclass CSemaphore  MY_UNCOPYABLE
139370b324cSopenharmony_ci{
140370b324cSopenharmony_ci  ::CSemaphore _object;
141370b324cSopenharmony_cipublic:
142370b324cSopenharmony_ci  CSemaphore() { Semaphore_Construct(&_object); }
143370b324cSopenharmony_ci  ~CSemaphore() { Close(); }
144370b324cSopenharmony_ci  WRes Close() { return Semaphore_Close(&_object); }
145370b324cSopenharmony_ci
146370b324cSopenharmony_ci  #ifdef _WIN32
147370b324cSopenharmony_ci  operator HANDLE() { return _object; }
148370b324cSopenharmony_ci  #endif
149370b324cSopenharmony_ci
150370b324cSopenharmony_ci  // bool IsCreated() const { return Semaphore_IsCreated(&_object) != 0; }
151370b324cSopenharmony_ci
152370b324cSopenharmony_ci  WRes Create(UInt32 initCount, UInt32 maxCount)
153370b324cSopenharmony_ci  {
154370b324cSopenharmony_ci    return Semaphore_Create(&_object, initCount, maxCount);
155370b324cSopenharmony_ci  }
156370b324cSopenharmony_ci  WRes OptCreateInit(UInt32 initCount, UInt32 maxCount)
157370b324cSopenharmony_ci  {
158370b324cSopenharmony_ci    return Semaphore_OptCreateInit(&_object, initCount, maxCount);
159370b324cSopenharmony_ci  }
160370b324cSopenharmony_ci  WRes Release() { return Semaphore_Release1(&_object); }
161370b324cSopenharmony_ci  WRes Release(UInt32 releaseCount) { return Semaphore_ReleaseN(&_object, releaseCount); }
162370b324cSopenharmony_ci  WRes Lock() { return Semaphore_Wait(&_object); }
163370b324cSopenharmony_ci};
164370b324cSopenharmony_ci
165370b324cSopenharmony_ciclass CCriticalSection  MY_UNCOPYABLE
166370b324cSopenharmony_ci{
167370b324cSopenharmony_ci  ::CCriticalSection _object;
168370b324cSopenharmony_cipublic:
169370b324cSopenharmony_ci  CCriticalSection() { CriticalSection_Init(&_object); }
170370b324cSopenharmony_ci  ~CCriticalSection() { CriticalSection_Delete(&_object); }
171370b324cSopenharmony_ci  void Enter() { CriticalSection_Enter(&_object); }
172370b324cSopenharmony_ci  void Leave() { CriticalSection_Leave(&_object); }
173370b324cSopenharmony_ci};
174370b324cSopenharmony_ci
175370b324cSopenharmony_ciclass CCriticalSectionLock  MY_UNCOPYABLE
176370b324cSopenharmony_ci{
177370b324cSopenharmony_ci  CCriticalSection *_object;
178370b324cSopenharmony_ci  void Unlock()  { _object->Leave(); }
179370b324cSopenharmony_cipublic:
180370b324cSopenharmony_ci  CCriticalSectionLock(CCriticalSection &object): _object(&object) {_object->Enter(); }
181370b324cSopenharmony_ci  ~CCriticalSectionLock() { Unlock(); }
182370b324cSopenharmony_ci};
183370b324cSopenharmony_ci
184370b324cSopenharmony_ci
185370b324cSopenharmony_ci#ifdef _WIN32
186370b324cSopenharmony_ci
187370b324cSopenharmony_citypedef HANDLE CHandle_WFMO;
188370b324cSopenharmony_citypedef CSemaphore CSemaphore_WFMO;
189370b324cSopenharmony_citypedef CAutoResetEvent CAutoResetEvent_WFMO;
190370b324cSopenharmony_citypedef CManualResetEvent CManualResetEvent_WFMO;
191370b324cSopenharmony_ci
192370b324cSopenharmony_ciinline DWORD WINAPI WaitForMultiObj_Any_Infinite(DWORD count, const CHandle_WFMO *handles)
193370b324cSopenharmony_ci{
194370b324cSopenharmony_ci  return ::WaitForMultipleObjects(count, handles, FALSE, INFINITE);
195370b324cSopenharmony_ci}
196370b324cSopenharmony_ci
197370b324cSopenharmony_ci#define SYNC_OBJ_DECL(obj)
198370b324cSopenharmony_ci#define SYNC_WFMO(x)
199370b324cSopenharmony_ci#define SYNC_PARAM(x)
200370b324cSopenharmony_ci#define SYNC_PARAM_DECL(x)
201370b324cSopenharmony_ci
202370b324cSopenharmony_ci#else //  _WIN32
203370b324cSopenharmony_ci
204370b324cSopenharmony_ci// POSIX sync objects for WaitForMultipleObjects
205370b324cSopenharmony_ci
206370b324cSopenharmony_ci#define SYNC_WFMO(x) x
207370b324cSopenharmony_ci#define SYNC_PARAM(x) x,
208370b324cSopenharmony_ci#define SYNC_PARAM_DECL(x) NWindows::NSynchronization::CSynchro *x
209370b324cSopenharmony_ci#define SYNC_OBJ_DECL(x) NWindows::NSynchronization::CSynchro x;
210370b324cSopenharmony_ci
211370b324cSopenharmony_ciclass CSynchro  MY_UNCOPYABLE
212370b324cSopenharmony_ci{
213370b324cSopenharmony_ci  pthread_mutex_t _mutex;
214370b324cSopenharmony_ci  pthread_cond_t _cond;
215370b324cSopenharmony_ci  bool _isValid;
216370b324cSopenharmony_ci
217370b324cSopenharmony_cipublic:
218370b324cSopenharmony_ci  CSynchro() { _isValid = false; }
219370b324cSopenharmony_ci  ~CSynchro()
220370b324cSopenharmony_ci  {
221370b324cSopenharmony_ci    if (_isValid)
222370b324cSopenharmony_ci    {
223370b324cSopenharmony_ci      ::pthread_mutex_destroy(&_mutex);
224370b324cSopenharmony_ci      ::pthread_cond_destroy(&_cond);
225370b324cSopenharmony_ci    }
226370b324cSopenharmony_ci    _isValid = false;
227370b324cSopenharmony_ci  }
228370b324cSopenharmony_ci  WRes Create()
229370b324cSopenharmony_ci  {
230370b324cSopenharmony_ci    RINOK(::pthread_mutex_init(&_mutex, NULL))
231370b324cSopenharmony_ci    const WRes ret = ::pthread_cond_init(&_cond, NULL);
232370b324cSopenharmony_ci    _isValid = 1;
233370b324cSopenharmony_ci    return ret;
234370b324cSopenharmony_ci  }
235370b324cSopenharmony_ci  WRes Enter()
236370b324cSopenharmony_ci  {
237370b324cSopenharmony_ci    return ::pthread_mutex_lock(&_mutex);
238370b324cSopenharmony_ci  }
239370b324cSopenharmony_ci  WRes Leave()
240370b324cSopenharmony_ci  {
241370b324cSopenharmony_ci    return ::pthread_mutex_unlock(&_mutex);
242370b324cSopenharmony_ci  }
243370b324cSopenharmony_ci  WRes WaitCond()
244370b324cSopenharmony_ci  {
245370b324cSopenharmony_ci    return ::pthread_cond_wait(&_cond, &_mutex);
246370b324cSopenharmony_ci  }
247370b324cSopenharmony_ci  WRes LeaveAndSignal()
248370b324cSopenharmony_ci  {
249370b324cSopenharmony_ci    const WRes res1 = ::pthread_cond_broadcast(&_cond);
250370b324cSopenharmony_ci    const WRes res2 = ::pthread_mutex_unlock(&_mutex);
251370b324cSopenharmony_ci    return (res2 ? res2 : res1);
252370b324cSopenharmony_ci  }
253370b324cSopenharmony_ci};
254370b324cSopenharmony_ci
255370b324cSopenharmony_ci
256370b324cSopenharmony_cistruct CBaseHandle_WFMO;
257370b324cSopenharmony_citypedef NWindows::NSynchronization::CBaseHandle_WFMO *CHandle_WFMO;
258370b324cSopenharmony_ci
259370b324cSopenharmony_ci// these constants are from Windows
260370b324cSopenharmony_ci#define WAIT_OBJECT_0 0
261370b324cSopenharmony_ci#define WAIT_FAILED ((DWORD)0xFFFFFFFF)
262370b324cSopenharmony_ci
263370b324cSopenharmony_ciDWORD WINAPI WaitForMultiObj_Any_Infinite(DWORD count, const CHandle_WFMO *handles);
264370b324cSopenharmony_ci
265370b324cSopenharmony_ci
266370b324cSopenharmony_cistruct CBaseHandle_WFMO  MY_UNCOPYABLE
267370b324cSopenharmony_ci{
268370b324cSopenharmony_ci  CSynchro *_sync;
269370b324cSopenharmony_ci
270370b324cSopenharmony_ci  CBaseHandle_WFMO(): _sync(NULL) {}
271370b324cSopenharmony_ci  virtual ~CBaseHandle_WFMO();
272370b324cSopenharmony_ci
273370b324cSopenharmony_ci  operator CHandle_WFMO() { return this; }
274370b324cSopenharmony_ci  virtual bool IsSignaledAndUpdate() = 0;
275370b324cSopenharmony_ci};
276370b324cSopenharmony_ci
277370b324cSopenharmony_ci
278370b324cSopenharmony_ciclass CBaseEvent_WFMO : public CBaseHandle_WFMO
279370b324cSopenharmony_ci{
280370b324cSopenharmony_ci  bool _manual_reset;
281370b324cSopenharmony_ci  bool _state;
282370b324cSopenharmony_ci
283370b324cSopenharmony_cipublic:
284370b324cSopenharmony_ci
285370b324cSopenharmony_ci  // bool IsCreated()  { return (this->_sync != NULL); }
286370b324cSopenharmony_ci  // CBaseEvent_WFMO()  { ; }
287370b324cSopenharmony_ci  // ~CBaseEvent_WFMO() Z7_override { Close(); }
288370b324cSopenharmony_ci
289370b324cSopenharmony_ci  WRes Close() { this->_sync = NULL; return 0; }
290370b324cSopenharmony_ci
291370b324cSopenharmony_ci  WRes Create(
292370b324cSopenharmony_ci      CSynchro *sync,
293370b324cSopenharmony_ci      bool manualReset, bool initiallyOwn)
294370b324cSopenharmony_ci  {
295370b324cSopenharmony_ci    this->_sync         = sync;
296370b324cSopenharmony_ci    this->_manual_reset = manualReset;
297370b324cSopenharmony_ci    this->_state        = initiallyOwn;
298370b324cSopenharmony_ci    return 0;
299370b324cSopenharmony_ci  }
300370b324cSopenharmony_ci
301370b324cSopenharmony_ci  WRes Set()
302370b324cSopenharmony_ci  {
303370b324cSopenharmony_ci    RINOK(this->_sync->Enter())
304370b324cSopenharmony_ci    this->_state = true;
305370b324cSopenharmony_ci    return this->_sync->LeaveAndSignal();
306370b324cSopenharmony_ci  }
307370b324cSopenharmony_ci
308370b324cSopenharmony_ci  WRes Reset()
309370b324cSopenharmony_ci  {
310370b324cSopenharmony_ci    RINOK(this->_sync->Enter())
311370b324cSopenharmony_ci    this->_state = false;
312370b324cSopenharmony_ci    return this->_sync->Leave();
313370b324cSopenharmony_ci  }
314370b324cSopenharmony_ci
315370b324cSopenharmony_ci  virtual bool IsSignaledAndUpdate() Z7_override;
316370b324cSopenharmony_ci};
317370b324cSopenharmony_ci
318370b324cSopenharmony_ci
319370b324cSopenharmony_ciclass CManualResetEvent_WFMO Z7_final: public CBaseEvent_WFMO
320370b324cSopenharmony_ci{
321370b324cSopenharmony_cipublic:
322370b324cSopenharmony_ci  WRes Create(CSynchro *sync, bool initiallyOwn = false) { return CBaseEvent_WFMO::Create(sync, true, initiallyOwn); }
323370b324cSopenharmony_ci};
324370b324cSopenharmony_ci
325370b324cSopenharmony_ci
326370b324cSopenharmony_ciclass CAutoResetEvent_WFMO Z7_final: public CBaseEvent_WFMO
327370b324cSopenharmony_ci{
328370b324cSopenharmony_cipublic:
329370b324cSopenharmony_ci  WRes Create(CSynchro *sync) { return CBaseEvent_WFMO::Create(sync, false, false); }
330370b324cSopenharmony_ci  WRes CreateIfNotCreated_Reset(CSynchro *sync)
331370b324cSopenharmony_ci  {
332370b324cSopenharmony_ci    return Create(sync);
333370b324cSopenharmony_ci  }
334370b324cSopenharmony_ci};
335370b324cSopenharmony_ci
336370b324cSopenharmony_ci
337370b324cSopenharmony_ciclass CSemaphore_WFMO Z7_final: public CBaseHandle_WFMO
338370b324cSopenharmony_ci{
339370b324cSopenharmony_ci  UInt32 _count;
340370b324cSopenharmony_ci  UInt32 _maxCount;
341370b324cSopenharmony_ci
342370b324cSopenharmony_cipublic:
343370b324cSopenharmony_ci  CSemaphore_WFMO() : _count(0), _maxCount(0) {}
344370b324cSopenharmony_ci
345370b324cSopenharmony_ci  WRes Close() { this->_sync = NULL; return 0; }
346370b324cSopenharmony_ci
347370b324cSopenharmony_ci  WRes Create(CSynchro *sync, UInt32 initCount, UInt32 maxCount)
348370b324cSopenharmony_ci  {
349370b324cSopenharmony_ci    if (initCount > maxCount || maxCount < 1)
350370b324cSopenharmony_ci      return EINVAL;
351370b324cSopenharmony_ci    this->_sync     = sync;
352370b324cSopenharmony_ci    this->_count    = initCount;
353370b324cSopenharmony_ci    this->_maxCount = maxCount;
354370b324cSopenharmony_ci    return 0;
355370b324cSopenharmony_ci  }
356370b324cSopenharmony_ci
357370b324cSopenharmony_ci  WRes Release(UInt32 releaseCount = 1)
358370b324cSopenharmony_ci  {
359370b324cSopenharmony_ci    if (releaseCount < 1)
360370b324cSopenharmony_ci      return EINVAL;
361370b324cSopenharmony_ci
362370b324cSopenharmony_ci    RINOK(this->_sync->Enter())
363370b324cSopenharmony_ci    UInt32 newCount = this->_count + releaseCount;
364370b324cSopenharmony_ci    if (newCount > this->_maxCount)
365370b324cSopenharmony_ci    {
366370b324cSopenharmony_ci      RINOK(this->_sync->Leave())
367370b324cSopenharmony_ci      return ERROR_TOO_MANY_POSTS; // EINVAL
368370b324cSopenharmony_ci    }
369370b324cSopenharmony_ci    this->_count = newCount;
370370b324cSopenharmony_ci
371370b324cSopenharmony_ci    return this->_sync->LeaveAndSignal();
372370b324cSopenharmony_ci  }
373370b324cSopenharmony_ci
374370b324cSopenharmony_ci  virtual bool IsSignaledAndUpdate() Z7_override;
375370b324cSopenharmony_ci};
376370b324cSopenharmony_ci
377370b324cSopenharmony_ci#endif // _WIN32
378370b324cSopenharmony_ci
379370b324cSopenharmony_ci}}
380370b324cSopenharmony_ci
381370b324cSopenharmony_ci#endif
382