1// Windows/Synchronization.h 2 3#ifndef ZIP7_INC_WINDOWS_SYNCHRONIZATION_H 4#define ZIP7_INC_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 != NULL) 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 != NULL) 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, NULL)) 231 const WRes ret = ::pthread_cond_init(&_cond, NULL); 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 const WRes res1 = ::pthread_cond_broadcast(&_cond); 250 const 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 virtual ~CBaseHandle_WFMO(); 272 273 operator CHandle_WFMO() { return this; } 274 virtual bool IsSignaledAndUpdate() = 0; 275}; 276 277 278class CBaseEvent_WFMO : public CBaseHandle_WFMO 279{ 280 bool _manual_reset; 281 bool _state; 282 283public: 284 285 // bool IsCreated() { return (this->_sync != NULL); } 286 // CBaseEvent_WFMO() { ; } 287 // ~CBaseEvent_WFMO() Z7_override { Close(); } 288 289 WRes Close() { this->_sync = NULL; return 0; } 290 291 WRes Create( 292 CSynchro *sync, 293 bool manualReset, bool initiallyOwn) 294 { 295 this->_sync = sync; 296 this->_manual_reset = manualReset; 297 this->_state = initiallyOwn; 298 return 0; 299 } 300 301 WRes Set() 302 { 303 RINOK(this->_sync->Enter()) 304 this->_state = true; 305 return this->_sync->LeaveAndSignal(); 306 } 307 308 WRes Reset() 309 { 310 RINOK(this->_sync->Enter()) 311 this->_state = false; 312 return this->_sync->Leave(); 313 } 314 315 virtual bool IsSignaledAndUpdate() Z7_override; 316}; 317 318 319class CManualResetEvent_WFMO Z7_final: public CBaseEvent_WFMO 320{ 321public: 322 WRes Create(CSynchro *sync, bool initiallyOwn = false) { return CBaseEvent_WFMO::Create(sync, true, initiallyOwn); } 323}; 324 325 326class CAutoResetEvent_WFMO Z7_final: public CBaseEvent_WFMO 327{ 328public: 329 WRes Create(CSynchro *sync) { return CBaseEvent_WFMO::Create(sync, false, false); } 330 WRes CreateIfNotCreated_Reset(CSynchro *sync) 331 { 332 return Create(sync); 333 } 334}; 335 336 337class CSemaphore_WFMO Z7_final: public CBaseHandle_WFMO 338{ 339 UInt32 _count; 340 UInt32 _maxCount; 341 342public: 343 CSemaphore_WFMO() : _count(0), _maxCount(0) {} 344 345 WRes Close() { this->_sync = NULL; return 0; } 346 347 WRes Create(CSynchro *sync, UInt32 initCount, UInt32 maxCount) 348 { 349 if (initCount > maxCount || maxCount < 1) 350 return EINVAL; 351 this->_sync = sync; 352 this->_count = initCount; 353 this->_maxCount = maxCount; 354 return 0; 355 } 356 357 WRes Release(UInt32 releaseCount = 1) 358 { 359 if (releaseCount < 1) 360 return EINVAL; 361 362 RINOK(this->_sync->Enter()) 363 UInt32 newCount = this->_count + releaseCount; 364 if (newCount > this->_maxCount) 365 { 366 RINOK(this->_sync->Leave()) 367 return ERROR_TOO_MANY_POSTS; // EINVAL 368 } 369 this->_count = newCount; 370 371 return this->_sync->LeaveAndSignal(); 372 } 373 374 virtual bool IsSignaledAndUpdate() Z7_override; 375}; 376 377#endif // _WIN32 378 379}} 380 381#endif 382