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