AuroraRuntime/Source/IPC/IPCPrimitives.NT.cpp
2022-04-16 19:26:01 +01:00

339 lines
8.1 KiB
C++
Executable File

/***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: IPCPrimitives.NT.cpp
Date: 2022-4-13
Author: Reece
***/
#include <Source/RuntimeInternal.hpp>
#include "IPC.hpp"
#include "IPCHandle.hpp"
#include "IPCPrimitives.NT.hpp"
#include <Source/Loop/LSMutex.hpp>
#include <Source/Loop/LSSemaphore.hpp>
#include <Source/Loop/LSEvent.hpp>
namespace Aurora::IPC
{
#define IMPLEMENT_HANDLE \
IPC::IPCHandle handle_; \
AuString ExportToString() override \
{ \
return handle_.ToString(); \
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Mutexes
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
struct IPCMutexProxy : IPCMutex, Loop::ILoopSourceEx
{
IPCMutexProxy(HANDLE h, const IPCHandle &handle);
~IPCMutexProxy();
PROXY_INTERNAL_INTERFACE(mutex_)
IMPLEMENT_HANDLE
bool Unlock() override;
bool IsSignaled() override;
bool WaitOn(AuUInt32 timeout) override;
Loop::ELoopSource GetType() override;
private:
Loop::LSMutex mutex_;
};
IPCMutexProxy::IPCMutexProxy(HANDLE h, const IPCHandle &handle) : handle_(handle), mutex_(h)
{
}
IPCMutexProxy::~IPCMutexProxy()
{
}
bool IPCMutexProxy::Unlock()
{
return this->mutex_.Unlock();
}
bool IPCMutexProxy::IsSignaled()
{
return this->mutex_.IsSignaled();
}
bool IPCMutexProxy::WaitOn(AuUInt32 timeout)
{
return this->mutex_.WaitOn(timeout);
}
Loop::ELoopSource IPCMutexProxy::GetType()
{
return this->mutex_.GetType();
}
AUKN_SYM AuSPtr<IPCMutex> NewMutex()
{
IPCHandle handle;
handle.NewId();
auto mutex = CreateMutexA(nullptr, false, handle.ToNTPath().c_str());
if (mutex == INVALID_HANDLE_VALUE)
{
SysPushErrorIO();
return {};
}
auto object = AuMakeShared<IPCMutexProxy>(mutex, handle);
if (!object)
{
SysPushErrorMem();
AuWin32CloseHandle(mutex);
return {};
}
return object;
}
AUKN_SYM AuSPtr<IPCMutex> ImportMutex(const AuString &handleString)
{
IPCHandle handle;
if (!handle.FromString(handleString))
{
SysPushErrorParseError();
return {};
}
auto mutex = OpenMutexA(MUTEX_ALL_ACCESS, false, handle.ToNTPath().c_str());
if (mutex == INVALID_HANDLE_VALUE)
{
SysPushErrorIO();
return {};
}
auto object = AuMakeShared<IPCMutexProxy>(mutex, handle);
if (!object)
{
SysPushErrorMem();
AuWin32CloseHandle(mutex);
return {};
}
return object;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Events
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
struct IPCEventProxy : IPCEvent, Loop::ILoopSourceEx
{
IPCEventProxy(HANDLE h, const IPCHandle &handle);
~IPCEventProxy();
PROXY_INTERNAL_INTERFACE(event_)
IMPLEMENT_HANDLE
bool Set() override;
bool Reset() override;
bool IsSignaled() override;
bool WaitOn(AuUInt32 timeout) override;
Loop::ELoopSource GetType() override;
private:
Loop::LSEvent event_;
};
IPCEventProxy::IPCEventProxy(HANDLE h, const IPCHandle &handle) : event_(h), handle_(handle)
{
}
IPCEventProxy::~IPCEventProxy()
{
}
bool IPCEventProxy::Set()
{
return this->event_.Set();
}
bool IPCEventProxy::Reset()
{
return this->event_.Reset();
}
bool IPCEventProxy::IsSignaled()
{
return this->event_.IsSignaled();
}
bool IPCEventProxy::WaitOn(AuUInt32 timeout)
{
return this->event_.WaitOn(timeout);
}
Loop::ELoopSource IPCEventProxy::GetType()
{
return this->event_.GetType();
}
AUKN_SYM AuSPtr<IPCEvent> NewEvent(bool triggered, bool atomicRelease)
{
IPCHandle handle;
handle.NewId();
auto mutex = CreateEventA(nullptr, !atomicRelease, triggered, handle.ToNTPath().c_str());
if (mutex == INVALID_HANDLE_VALUE)
{
SysPushErrorIO();
return {};
}
auto object = AuMakeShared<IPCEventProxy>(mutex, handle);
if (!object)
{
SysPushErrorMem();
AuWin32CloseHandle(mutex);
return {};
}
return object;
}
AUKN_SYM AuSPtr<IPCEvent> ImportEvent(const AuString &handleString)
{
IPCHandle handle;
if (!handle.FromString(handleString))
{
SysPushErrorParseError();
return {};
}
auto mutex = OpenEventA(EVENT_ALL_ACCESS, false, handle.ToNTPath().c_str());
if (mutex == INVALID_HANDLE_VALUE)
{
SysPushErrorIO();
return {};
}
auto object = AuMakeShared<IPCEventProxy>(mutex, handle);
if (!object)
{
SysPushErrorMem();
AuWin32CloseHandle(mutex);
return {};
}
return object;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Semaphores
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
struct IPCSemaphoreProxy : IPCSemaphore, Loop::ILoopSourceEx
{
IPCSemaphoreProxy(HANDLE h, const IPCHandle &handle);
~IPCSemaphoreProxy();
PROXY_INTERNAL_INTERFACE(semaphore_)
IMPLEMENT_HANDLE
bool AddOne() override;
bool IsSignaled() override;
bool WaitOn(AuUInt32 timeout) override;
Loop::ELoopSource GetType() override;
private:
Loop::LSSemaphore semaphore_;
};
IPCSemaphoreProxy::IPCSemaphoreProxy(HANDLE h, const IPCHandle &handle) : handle_(handle), semaphore_(h)
{
}
IPCSemaphoreProxy::~IPCSemaphoreProxy()
{
}
bool IPCSemaphoreProxy::AddOne()
{
return this->semaphore_.AddOne();
}
bool IPCSemaphoreProxy::IsSignaled()
{
return this->semaphore_.IsSignaled();
}
bool IPCSemaphoreProxy::WaitOn(AuUInt32 timeout)
{
return this->semaphore_.WaitOn(timeout);
}
Loop::ELoopSource IPCSemaphoreProxy::GetType()
{
return this->semaphore_.GetType();
}
AUKN_SYM AuSPtr<IPCSemaphore> NewSemaphore(int startingValue)
{
IPCHandle handle;
handle.NewId();
auto mutex = CreateSemaphoreA(nullptr, startingValue, AuNumericLimits<LONG>::max(), handle.ToNTPath().c_str());
if (mutex == INVALID_HANDLE_VALUE)
{
SysPushErrorIO();
return {};
}
auto object = AuMakeShared<IPCSemaphoreProxy>(mutex, handle);
if (!object)
{
SysPushErrorMem();
AuWin32CloseHandle(mutex);
return {};
}
return object;
}
AUKN_SYM AuSPtr<IPCSemaphore> ImportSemaphore(const AuString &handleString)
{
IPCHandle handle;
if (!handle.FromString(handleString))
{
SysPushErrorParseError();
return {};
}
auto mutex = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, false, handle.ToNTPath().c_str());
if (mutex == INVALID_HANDLE_VALUE)
{
SysPushErrorIO();
return {};
}
auto object = AuMakeShared<IPCSemaphoreProxy>(mutex, handle);
if (!object)
{
SysPushErrorMem();
AuWin32CloseHandle(mutex);
return {};
}
return object;
}
}