/*** Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: AuIPCPrimitives.Linux.cpp Date: 2022-4-13 Author: Reece ***/ #include #include "IPC.hpp" #include "IPCHandle.hpp" #include "IPCPrimitives.Linux.hpp" #include namespace Aurora::IO::IPC { ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Events ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// IPCEventProxy::IPCEventProxy(bool triggered, bool atomicRelease) : event_(triggered, atomicRelease, true) { IPC::IPCToken token; if (this->event_.HasValidHandle()) { if (IO::UNIX::FDServe(this->GetHandle(), token)) { token.word = AuUInt32(atomicRelease); this->handle_.PushId(EIPCHandleType::eIPCPrimitiveEvent, token); } else { this->event_.~LSEvent(); } } } IPCEventProxy::IPCEventProxy(int handle, bool triggered, bool atomicRelease) : event_(handle, triggered, atomicRelease) { IPC::IPCToken token; if (this->event_.HasValidHandle()) { if (IO::UNIX::FDServe(this->GetHandle(), token)) { token.word = AuUInt32(atomicRelease); this->handle_.PushId(EIPCHandleType::eIPCPrimitiveEvent, token); } else { this->event_.~LSEvent(); } } } IPCEventProxy::~IPCEventProxy() { if (this->handle_.values.size() == 1) { IO::UNIX::FDServeEnd(this->handle_.values[0].token); this->handle_ = {}; } } 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 NewEvent(bool triggered, bool atomicRelease) { auto object = AuMakeShared(triggered, atomicRelease); if (!object) { SysPushErrorMem(); return {}; } if (!object->HasValidHandle()) { SysPushErrorIO(); return {}; } return object; } AuSPtr ImportEventEx(const IPCToken &token) { int fd {-1}; if (!IO::UNIX::FDAccept(token, fd)) { SysPushErrorNested(); return {}; } auto object = AuMakeShared(fd, false, bool(token.word)); if (!object) { SysPushErrorMem(); ::close(fd); return {}; } if (!object->HasValidHandle()) { SysPushErrorIO(); return {}; } return object; } AUKN_SYM AuSPtr ImportEvent(const AuString &handle) { IPC::IPCHandle decodedHandle; if (!decodedHandle.FromString(handle)) { SysPushErrorParseError("Invalid handle: {}", handle); return {}; } auto val = decodedHandle.GetToken(IPC::EIPCHandleType::eIPCPrimitiveEvent, 0); if (!val) { SysPushErrorParseError("Invalid handle: {}", handle); return {}; } return ImportEventEx(val->token); } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Semaphores ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// IPCSemaphoreProxy::IPCSemaphoreProxy(AuUInt32 initialCount) : semaphore_(initialCount) { IPC::IPCToken token; if (this->semaphore_.HasValidHandle()) { if (IO::UNIX::FDServe(this->GetHandle(), token)) { this->handle_.PushId(EIPCHandleType::eIPCPrimitiveSemaphore, token); } else { this->semaphore_.~LSSemaphore(); } } } IPCSemaphoreProxy::IPCSemaphoreProxy(int handle, int tag) : semaphore_(handle, tag) { IPC::IPCToken token; if (this->semaphore_.HasValidHandle()) { if (IO::UNIX::FDServe(this->GetHandle(), token)) { this->handle_.PushId(EIPCHandleType::eIPCPrimitiveSemaphore, token); } else { this->semaphore_.~LSSemaphore(); } } } IPCSemaphoreProxy::~IPCSemaphoreProxy() { if (this->handle_.values.size() == 1) { IO::UNIX::FDServeEnd(this->handle_.values[0].token); this->handle_ = {}; } } 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 NewSemaphore(int startingValue) { auto object = AuMakeShared(startingValue); if (!object) { SysPushErrorMem(); return {}; } if (!object->HasValidHandle()) { SysPushErrorIO(); return {}; } return object; } AUKN_SYM AuSPtr ImportSemaphore(const AuString &handle) { IPC::IPCHandle decodedHandle; if (!decodedHandle.FromString(handle)) { SysPushErrorParseError("Invalid handle: {}", handle); return {}; } auto val = decodedHandle.GetToken(IPC::EIPCHandleType::eIPCPrimitiveSemaphore, 0); if (!val) { SysPushErrorParseError("Invalid handle: {}", handle); return {}; } int fd {-1}; if (!IO::UNIX::FDAccept(val->token, fd)) { SysPushErrorNested(); return {}; } auto object = AuMakeShared(fd, 0xC001C0DE); if (!object) { SysPushErrorMem(); ::close(fd); return {}; } if (!object->HasValidHandle()) { SysPushErrorIO(); return {}; } return object; } }