#include "stdafx.h"
#include "hwinsynch.h"
namespace harlinn
{
namespace windows
{
HARLINN_WINDOWS_IMPLEMENT_STANDARD_EXCEPTION_MEMBERS(AbandonedMutexException)
// ----------------------------------------------------------------------
// WaitableHandle
// ----------------------------------------------------------------------
HWIN_EXPORT void WaitableHandle::ThrowAbandonedMutexException()
{
throw AbandonedMutexException();
}
HWIN_EXPORT bool WaitableHandle::Wait()
{
return Wait(Timeout::Infinite);
}
HWIN_EXPORT bool WaitableHandle::Wait(DWORD timeoutInMillis)
{
if(!IsValid())
{
ThrowInvalidHandle();
}
auto ret = WaitForSingleObject(Value(), timeoutInMillis);
if(ret == WAIT_ABANDONED)
{
ThrowAbandonedMutexException();
}
if(ret == WAIT_FAILED)
{
ThrowLastOSError();
}
return ret != WAIT_TIMEOUT;
}
HWIN_EXPORT bool WaitableHandle::Wait(const TimeSpan& timeout)
{
DWORD timeoutInMillis = DWORD(timeout.TotalMilliseconds());
return Wait(timeoutInMillis);
}
HWIN_EXPORT bool WaitableHandle::Wait(bool alertable)
{
return Wait(Timeout::Infinite,alertable);
}
HWIN_EXPORT bool WaitableHandle::Wait(DWORD timeoutInMillis, bool alertable)
{
if(!IsValid())
{
ThrowInvalidHandle();
}
auto ret = WaitForSingleObjectEx(Value(), timeoutInMillis,alertable?TRUE:FALSE);
if(ret == WAIT_ABANDONED)
{
ThrowAbandonedMutexException();
}
if(ret == WAIT_FAILED)
{
ThrowLastOSError();
}
return ret != WAIT_TIMEOUT;
}
HWIN_EXPORT bool WaitableHandle::Wait(const TimeSpan& timeout, bool alertable)
{
DWORD timeoutInMillis = DWORD(timeout.TotalMilliseconds());
return Wait(timeoutInMillis,alertable);
}
HWIN_EXPORT int WaitableHandle::WaitForAnyOf(size_t numberOfHandles,HANDLE* handles,DWORD timeoutInMillis)
{
if(numberOfHandles > MAXIMUM_WAIT_OBJECTS)
{
throw ArgumentException("numberOfHandles");
}
auto ret = WaitForMultipleObjects(DWORD(numberOfHandles),handles,FALSE,timeoutInMillis);
if((ret >= WAIT_ABANDONED_0)&&(ret < (WAIT_ABANDONED_0 + numberOfHandles) ))
{
ThrowAbandonedMutexException();
}
if(ret == WAIT_FAILED)
{
ThrowLastOSError();
}
if(ret == WAIT_TIMEOUT)
{
return WaitTimeout;
}
return ret - WAIT_OBJECT_0;
}
HWIN_EXPORT int WaitableHandle::WaitForAnyOf(size_t numberOfHandles,HANDLE* handles,DWORD timeoutInMillis,bool alertable)
{
if(numberOfHandles > MAXIMUM_WAIT_OBJECTS)
{
throw ArgumentException("numberOfHandles");
}
auto ret = WaitForMultipleObjectsEx(DWORD(numberOfHandles),handles,FALSE,timeoutInMillis,alertable?TRUE:FALSE);
if((ret >= WAIT_ABANDONED_0)&&(ret < (WAIT_ABANDONED_0 + numberOfHandles) ))
{
ThrowAbandonedMutexException();
}
if(ret == WAIT_FAILED)
{
ThrowLastOSError();
}
if(ret == WAIT_TIMEOUT)
{
return WaitTimeout;
}
return ret - WAIT_OBJECT_0;
}
HWIN_EXPORT int WaitableHandle::WaitForAllOf(size_t numberOfHandles,HANDLE* handles,DWORD timeoutInMillis)
{
if(numberOfHandles > MAXIMUM_WAIT_OBJECTS)
{
throw ArgumentException("numberOfHandles");
}
auto ret = WaitForMultipleObjects(DWORD(numberOfHandles),handles,TRUE,timeoutInMillis);
if((ret >= WAIT_ABANDONED_0)&&(ret < (WAIT_ABANDONED_0 + numberOfHandles) ))
{
ThrowAbandonedMutexException();
}
if(ret == WAIT_FAILED)
{
ThrowLastOSError();
}
if(ret == WAIT_TIMEOUT)
{
return WaitTimeout;
}
return ret - WAIT_OBJECT_0;
}
HWIN_EXPORT int WaitableHandle::WaitForAllOf(size_t numberOfHandles,HANDLE* handles,DWORD timeoutInMillis,bool alertable)
{
if(numberOfHandles > MAXIMUM_WAIT_OBJECTS)
{
throw ArgumentException("numberOfHandles");
}
auto ret = WaitForMultipleObjectsEx(DWORD(numberOfHandles),handles,TRUE,timeoutInMillis,alertable?TRUE:FALSE);
if((ret >= WAIT_ABANDONED_0)&&(ret < (WAIT_ABANDONED_0 + numberOfHandles) ))
{
ThrowAbandonedMutexException();
}
if(ret == WAIT_FAILED)
{
ThrowLastOSError();
}
if(ret == WAIT_TIMEOUT)
{
return WaitTimeout;
}
return ret - WAIT_OBJECT_0;
}
HWIN_EXPORT int WaitableHandle::WaitForAnyOf(const std::vector< std::shared_ptr< WaitableHandle > >& waitableHandles,DWORD timeoutInMillis)
{
size_t size = waitableHandles.size();
if( size > MAXIMUM_WAIT_OBJECTS)
{
throw ArgumentException("numberOfHandles");
}
HANDLE handles[MAXIMUM_WAIT_OBJECTS];
for(size_t i = 0; i < size; i++)
{
std::shared_ptr< WaitableHandle > waitableHandle = waitableHandles.at(i);
handles[i] = waitableHandle->GetHANDLE();
}
return WaitForAnyOf(size,handles,timeoutInMillis);
}
HWIN_EXPORT int WaitableHandle::WaitForAnyOf(const std::vector< std::shared_ptr< WaitableHandle > >& waitableHandles,DWORD timeoutInMillis,bool alertable)
{
size_t size = waitableHandles.size();
if( size > MAXIMUM_WAIT_OBJECTS)
{
throw ArgumentException("numberOfHandles");
}
HANDLE handles[MAXIMUM_WAIT_OBJECTS];
for(size_t i = 0; i < size; i++)
{
std::shared_ptr< WaitableHandle > waitableHandle = waitableHandles.at(i);
handles[i] = waitableHandle->GetHANDLE();
}
return WaitForAnyOf(size,handles,timeoutInMillis,alertable);
}
HWIN_EXPORT int WaitableHandle::WaitForAllOf(const std::vector< std::shared_ptr< WaitableHandle > >& waitableHandles,DWORD timeoutInMillis)
{
size_t size = waitableHandles.size();
if( size > MAXIMUM_WAIT_OBJECTS)
{
throw ArgumentException("numberOfHandles");
}
HANDLE handles[MAXIMUM_WAIT_OBJECTS];
for(size_t i = 0; i < size; i++)
{
std::shared_ptr< WaitableHandle > waitableHandle = waitableHandles.at(i);
handles[i] = waitableHandle->GetHANDLE();
}
return WaitForAllOf(size,handles,timeoutInMillis);
}
HWIN_EXPORT int WaitableHandle::WaitForAllOf(const std::vector< std::shared_ptr< WaitableHandle > >& waitableHandles,DWORD timeoutInMillis,bool alertable)
{
size_t size = waitableHandles.size();
if( size > MAXIMUM_WAIT_OBJECTS)
{
throw ArgumentException("numberOfHandles");
}
HANDLE handles[MAXIMUM_WAIT_OBJECTS];
for(size_t i = 0; i < size; i++)
{
std::shared_ptr< WaitableHandle > waitableHandle = waitableHandles.at(i);
handles[i] = waitableHandle->GetHANDLE();
}
return WaitForAllOf(size,handles,timeoutInMillis,alertable);
}
HWIN_EXPORT int WaitableHandle::WaitForAnyOf(const std::vector< std::shared_ptr< WaitableHandle > >& waitableHandles)
{
return WaitForAnyOf(waitableHandles,Timeout::Infinite);
}
HWIN_EXPORT int WaitableHandle::WaitForAnyOf(const std::vector< std::shared_ptr< WaitableHandle > >& waitableHandles,bool alertable)
{
return WaitForAnyOf(waitableHandles,Timeout::Infinite,alertable);
}
HWIN_EXPORT int WaitableHandle::WaitForAllOf(const std::vector< std::shared_ptr< WaitableHandle > >& waitableHandles)
{
return WaitForAllOf(waitableHandles,Timeout::Infinite);
}
HWIN_EXPORT int WaitableHandle::WaitForAllOf(const std::vector< std::shared_ptr< WaitableHandle > >& waitableHandles,bool alertable)
{
return WaitForAllOf(waitableHandles,Timeout::Infinite,alertable);
}
// ----------------------------------------------------------------------
// EventWaitHandle
// ----------------------------------------------------------------------
HWIN_EXPORT HANDLE EventWaitHandle::CreateEvent(SECURITY_ATTRIBUTES* eventAttributes, wchar_t* name, bool initiallySet, bool manualReset, EventWaitHandleRights desiredAccess)
{
DWORD flags = 0;
if(initiallySet)
{
flags = CREATE_EVENT_INITIAL_SET;
}
if(manualReset)
{
flags |= CREATE_EVENT_MANUAL_RESET;
}
auto result = CreateEventExW(eventAttributes, name, flags, DWORD(desiredAccess));
if(result == 0)
{
ThrowLastOSError();
}
return result;
}
HWIN_EXPORT HANDLE EventWaitHandle::Open(wchar_t* name,EventWaitHandleRights desiredAccess, bool inheritHandle)
{
auto result = OpenEventW(DWORD(desiredAccess),inheritHandle,name);
if(result == 0)
{
ThrowLastOSError();
}
return result;
}
HWIN_EXPORT EventWaitHandle::EventWaitHandle(SECURITY_ATTRIBUTES* eventAttributes, wchar_t* name, bool initiallySet, bool manualReset, EventWaitHandleRights desiredAccess )
: Base( CreateEvent(eventAttributes, name, initiallySet, manualReset, desiredAccess),true)
{
}
HWIN_EXPORT EventWaitHandle::EventWaitHandle(wchar_t* name, bool initiallySet, bool manualReset, EventWaitHandleRights desiredAccess )
: Base( CreateEvent(nullptr, name, initiallySet, manualReset, desiredAccess),true)
{
}
HWIN_EXPORT EventWaitHandle::EventWaitHandle(bool initiallySet, bool manualReset, EventWaitHandleRights desiredAccess )
: Base( CreateEvent(nullptr, nullptr, initiallySet, manualReset, desiredAccess),true)
{
}
HWIN_EXPORT std::shared_ptr<EventWaitHandle> EventWaitHandle::OpenExisting(wchar_t* name, EventWaitHandleRights desiredAccess, bool inheritHandle)
{
auto handle = Open(name,desiredAccess,inheritHandle);
auto result = std::make_shared<EventWaitHandle>(handle,true);
return result;
}
HWIN_EXPORT bool EventWaitHandle::Set()
{
if(!IsValid())
{
ThrowInvalidHandle();
}
return SetEvent(Value()) != FALSE;
}
HWIN_EXPORT bool EventWaitHandle::Reset()
{
if(!IsValid())
{
ThrowInvalidHandle();
}
return ResetEvent(Value()) != FALSE;
}
// ----------------------------------------------------------------------
// AutoResetEvent
// ----------------------------------------------------------------------
HWIN_EXPORT AutoResetEvent::AutoResetEvent(bool initiallySet)
: Base(initiallySet,false)
{
}
// ----------------------------------------------------------------------
// ManualResetEvent
// ----------------------------------------------------------------------
HWIN_EXPORT ManualResetEvent::ManualResetEvent(bool initiallySet)
: Base(initiallySet,true)
{
}
// ----------------------------------------------------------------------
// Mutex
// ----------------------------------------------------------------------
HWIN_EXPORT HANDLE Mutex::Create( SECURITY_ATTRIBUTES* eventAttributes, wchar_t* name, bool initiallyOwned, MutexRights desiredAccess )
{
HANDLE result = CreateMutexExW(eventAttributes, name, initiallyOwned?CREATE_MUTEX_INITIAL_OWNER:0 , DWORD(desiredAccess));
if(result == nullptr)
{
ThrowLastOSError();
}
return result;
}
HWIN_EXPORT HANDLE Mutex::Open(wchar_t* name, MutexRights desiredAccess, bool inheritHandle )
{
HANDLE result = OpenMutexW(DWORD(desiredAccess),inheritHandle,name);
if(result == nullptr)
{
ThrowLastOSError();
}
return result;
}
HWIN_EXPORT Mutex::Mutex( SECURITY_ATTRIBUTES* eventAttributes, wchar_t* name, bool initiallyOwned, MutexRights desiredAccess )
: Base(Create(eventAttributes, name, initiallyOwned, desiredAccess),true)
{
}
HWIN_EXPORT Mutex::Mutex( wchar_t* name, bool initiallyOwned , MutexRights desiredAccess )
: Base(Create(nullptr, name, initiallyOwned, desiredAccess),true)
{
}
HWIN_EXPORT Mutex::Mutex( bool initiallyOwned , MutexRights desiredAccess )
: Base(Create(nullptr, nullptr, initiallyOwned, desiredAccess),true)
{
}
HWIN_EXPORT std::shared_ptr<Mutex> Mutex::OpenExisting(wchar_t* name, MutexRights desiredAccess , bool inheritHandle)
{
HANDLE h = Open(name, desiredAccess , inheritHandle);
auto result = std::make_shared<Mutex>(h);
return result;
}
HWIN_EXPORT Mutex& Mutex::Release()
{
if(ReleaseMutex(GetHANDLE()) == FALSE)
{
ThrowLastOSError();
}
return *this;
}
// ----------------------------------------------------------------------
// CriticalSection
// ----------------------------------------------------------------------
HWIN_EXPORT CriticalSection::CriticalSection()
{
InitializeCriticalSection(&criticalSection);
}
HWIN_EXPORT CriticalSection::CriticalSection(DWORD spinCount)
{
InitializeCriticalSectionAndSpinCount(&criticalSection,spinCount);
}
HWIN_EXPORT bool CriticalSection::Wait()
{
EnterCriticalSection(&criticalSection);
return true;
}
HWIN_EXPORT bool CriticalSection::TryWait()
{
return TryEnterCriticalSection(&criticalSection)?true:false;
}
HWIN_EXPORT CriticalSection& CriticalSection::Release()
{
LeaveCriticalSection(&criticalSection);
return *this;
}
}
}