// Windows/Synchronization.h #ifndef __WINDOWS_SYNCHRONIZATION_H #define __WINDOWS_SYNCHRONIZATION_H #include "../../C/Threads.h" #include "../Common/MyTypes.h" #include "Defs.h" #ifdef _WIN32 #include "Handle.h" #endif namespace NWindows { namespace NSynchronization { class CBaseEvent MY_UNCOPYABLE { protected: ::CEvent _object; public: bool IsCreated() { return Event_IsCreated(&_object) != 0; } CBaseEvent() { Event_Construct(&_object); } ~CBaseEvent() { Close(); } WRes Close() { return Event_Close(&_object); } #ifdef _WIN32 operator HANDLE() { return _object; } WRes Create(bool manualReset, bool initiallyOwn, LPCTSTR name = NULL, LPSECURITY_ATTRIBUTES sa = NULL) { _object = ::CreateEvent(sa, BoolToBOOL(manualReset), BoolToBOOL(initiallyOwn), name); if (name == NULL && _object != 0) return 0; return ::GetLastError(); } WRes Open(DWORD desiredAccess, bool inheritHandle, LPCTSTR name) { _object = ::OpenEvent(desiredAccess, BoolToBOOL(inheritHandle), name); if (_object != 0) return 0; return ::GetLastError(); } #endif WRes Set() { return Event_Set(&_object); } // bool Pulse() { return BOOLToBool(::PulseEvent(_handle)); } WRes Reset() { return Event_Reset(&_object); } WRes Lock() { return Event_Wait(&_object); } }; class CManualResetEvent: public CBaseEvent { public: WRes Create(bool initiallyOwn = false) { return ManualResetEvent_Create(&_object, initiallyOwn ? 1: 0); } WRes CreateIfNotCreated_Reset() { if (IsCreated()) return Reset(); return ManualResetEvent_CreateNotSignaled(&_object); } #ifdef _WIN32 WRes CreateWithName(bool initiallyOwn, LPCTSTR name) { return CBaseEvent::Create(true, initiallyOwn, name); } #endif }; class CAutoResetEvent: public CBaseEvent { public: WRes Create() { return AutoResetEvent_CreateNotSignaled(&_object); } WRes CreateIfNotCreated_Reset() { if (IsCreated()) return Reset(); return AutoResetEvent_CreateNotSignaled(&_object); } }; /* #ifdef _WIN32 class CObject: public CHandle { public: WRes Lock(DWORD timeoutInterval = INFINITE) { return (::WaitForSingleObject(_handle, timeoutInterval) == WAIT_OBJECT_0 ? 0 : ::GetLastError()); } }; class CMutex: public CObject { public: WRes Create(bool initiallyOwn, LPCTSTR name = NULL, LPSECURITY_ATTRIBUTES sa = NULL) { _handle = ::CreateMutex(sa, BoolToBOOL(initiallyOwn), name); if (name == NULL && _handle != 0) return 0; return ::GetLastError(); } #ifndef UNDER_CE WRes Open(DWORD desiredAccess, bool inheritHandle, LPCTSTR name) { _handle = ::OpenMutex(desiredAccess, BoolToBOOL(inheritHandle), name); if (_handle != 0) return 0; return ::GetLastError(); } #endif WRes Release() { return ::ReleaseMutex(_handle) ? 0 : ::GetLastError(); } }; class CMutexLock MY_UNCOPYABLE { CMutex *_object; public: CMutexLock(CMutex &object): _object(&object) { _object->Lock(); } ~CMutexLock() { _object->Release(); } }; #endif // _WIN32 */ class CSemaphore MY_UNCOPYABLE { ::CSemaphore _object; public: CSemaphore() { Semaphore_Construct(&_object); } ~CSemaphore() { Close(); } WRes Close() { return Semaphore_Close(&_object); } #ifdef _WIN32 operator HANDLE() { return _object; } #endif // bool IsCreated() const { return Semaphore_IsCreated(&_object) != 0; } WRes Create(UInt32 initCount, UInt32 maxCount) { return Semaphore_Create(&_object, initCount, maxCount); } WRes OptCreateInit(UInt32 initCount, UInt32 maxCount) { return Semaphore_OptCreateInit(&_object, initCount, maxCount); } WRes Release() { return Semaphore_Release1(&_object); } WRes Release(UInt32 releaseCount) { return Semaphore_ReleaseN(&_object, releaseCount); } WRes Lock() { return Semaphore_Wait(&_object); } }; class CCriticalSection MY_UNCOPYABLE { ::CCriticalSection _object; public: CCriticalSection() { CriticalSection_Init(&_object); } ~CCriticalSection() { CriticalSection_Delete(&_object); } void Enter() { CriticalSection_Enter(&_object); } void Leave() { CriticalSection_Leave(&_object); } }; class CCriticalSectionLock MY_UNCOPYABLE { CCriticalSection *_object; void Unlock() { _object->Leave(); } public: CCriticalSectionLock(CCriticalSection &object): _object(&object) {_object->Enter(); } ~CCriticalSectionLock() { Unlock(); } }; #ifdef _WIN32 typedef HANDLE CHandle_WFMO; typedef CSemaphore CSemaphore_WFMO; typedef CAutoResetEvent CAutoResetEvent_WFMO; typedef CManualResetEvent CManualResetEvent_WFMO; inline DWORD WINAPI WaitForMultiObj_Any_Infinite(DWORD count, const CHandle_WFMO *handles) { return ::WaitForMultipleObjects(count, handles, FALSE, INFINITE); } #define SYNC_OBJ_DECL(obj) #define SYNC_WFMO(x) #define SYNC_PARAM(x) #define SYNC_PARAM_DECL(x) #else // _WIN32 // POSIX sync objects for WaitForMultipleObjects #define SYNC_WFMO(x) x #define SYNC_PARAM(x) x, #define SYNC_PARAM_DECL(x) NWindows::NSynchronization::CSynchro *x #define SYNC_OBJ_DECL(x) NWindows::NSynchronization::CSynchro x; class CSynchro MY_UNCOPYABLE { pthread_mutex_t _mutex; pthread_cond_t _cond; bool _isValid; public: CSynchro() { _isValid = false; } ~CSynchro() { if (_isValid) { ::pthread_mutex_destroy(&_mutex); ::pthread_cond_destroy(&_cond); } _isValid = false; } WRes Create() { RINOK(::pthread_mutex_init(&_mutex, 0)); WRes ret = ::pthread_cond_init(&_cond, 0); _isValid = 1; return ret; } WRes Enter() { return ::pthread_mutex_lock(&_mutex); } WRes Leave() { return ::pthread_mutex_unlock(&_mutex); } WRes WaitCond() { return ::pthread_cond_wait(&_cond, &_mutex); } WRes LeaveAndSignal() { WRes res1 = ::pthread_cond_broadcast(&_cond); WRes res2 = ::pthread_mutex_unlock(&_mutex); return (res2 ? res2 : res1); } }; struct CBaseHandle_WFMO; typedef NWindows::NSynchronization::CBaseHandle_WFMO *CHandle_WFMO; // these constants are from Windows #define WAIT_OBJECT_0 0 #define WAIT_FAILED ((DWORD)0xFFFFFFFF) DWORD WINAPI WaitForMultiObj_Any_Infinite(DWORD count, const CHandle_WFMO *handles); struct CBaseHandle_WFMO MY_UNCOPYABLE { CSynchro *_sync; CBaseHandle_WFMO(): _sync(NULL) {} operator CHandle_WFMO() { return this; } virtual bool IsSignaledAndUpdate() = 0; }; class CBaseEvent_WFMO : public CBaseHandle_WFMO { bool _manual_reset; bool _state; public: // bool IsCreated() { return (this->_sync != NULL); } // CBaseEvent_WFMO() { ; } ~CBaseEvent_WFMO() { Close(); } WRes Close() { this->_sync = NULL; return 0; } WRes Create( CSynchro *sync, bool manualReset, bool initiallyOwn) { this->_sync = sync; this->_manual_reset = manualReset; this->_state = initiallyOwn; return 0; } WRes Set() { RINOK(this->_sync->Enter()); this->_state = true; return this->_sync->LeaveAndSignal(); } WRes Reset() { RINOK(this->_sync->Enter()); this->_state = false; return this->_sync->Leave(); } virtual bool IsSignaledAndUpdate() { if (this->_state == false) return false; if (this->_manual_reset == false) this->_state = false; return true; } }; class CManualResetEvent_WFMO: public CBaseEvent_WFMO { public: WRes Create(CSynchro *sync, bool initiallyOwn = false) { return CBaseEvent_WFMO::Create(sync, true, initiallyOwn); } }; class CAutoResetEvent_WFMO: public CBaseEvent_WFMO { public: WRes Create(CSynchro *sync) { return CBaseEvent_WFMO::Create(sync, false, false); } WRes CreateIfNotCreated_Reset(CSynchro *sync) { return Create(sync); } }; class CSemaphore_WFMO : public CBaseHandle_WFMO { UInt32 _count; UInt32 _maxCount; public: CSemaphore_WFMO() : _count(0), _maxCount(0) {} WRes Close() { this->_sync = NULL; return 0; } WRes Create(CSynchro *sync, UInt32 initCount, UInt32 maxCount) { if (initCount > maxCount || maxCount < 1) return EINVAL; this->_sync = sync; this->_count = initCount; this->_maxCount = maxCount; return 0; } WRes Release(UInt32 releaseCount = 1) { if (releaseCount < 1) return EINVAL; RINOK(this->_sync->Enter()); UInt32 newCount = this->_count + releaseCount; if (newCount > this->_maxCount) { RINOK(this->_sync->Leave()); return ERROR_TOO_MANY_POSTS; // EINVAL } this->_count = newCount; return this->_sync->LeaveAndSignal(); } virtual bool IsSignaledAndUpdate() { if (this->_count == 0) return false; this->_count--; return true; } }; #endif // _WIN32 }} #endif