mirror of
https://github.com/holub/mame
synced 2025-06-04 03:46:29 +03:00
394 lines
8.5 KiB
C++
394 lines
8.5 KiB
C++
// 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
|