/*** Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: LSEvent.Linux.cpp Date: 2022-4-4 Author: Reece ***/ #include #include "LSEvent.hpp" #include "LSFromFdNonblocking.hpp" namespace Aurora::Loop { LSEvent::LSEvent(bool triggered, bool atomicRelease, bool permitMultipleTriggers) : atomicRelease_(atomicRelease) { Init(triggered); } LSEvent::LSEvent(int handle, bool triggered, bool atomicRelease) : atomicRelease_(atomicRelease) { this->handle = handle; } LSEvent::~LSEvent() { if ((this->handle != 0) && (this->handle != -1)) { close(AuExchange(this->handle, -1)); } } bool LSEvent::OnTrigger(AuUInt handle) { AuUInt64 oldSemaphoreValue {}; if (!this->atomicRelease_) { return true; } return read(this->handle, &oldSemaphoreValue, sizeof(oldSemaphoreValue)) == 8; } void LSEvent::Init(bool init) { this->handle = eventfd(init ? 1 : 0, EFD_NONBLOCK); } bool LSEvent::Set() { AuUInt64 plsNoOverflow {1}; if (write(this->handle, &plsNoOverflow, sizeof(plsNoOverflow)) != 8) { // todo push error return false; } return true; } bool LSEvent::Reset() { AuUInt64 oldSemaphoreValue {0}; // RETURN VALUE IS USELESS - Failure is to be expected read(this->handle, &oldSemaphoreValue, sizeof(oldSemaphoreValue)); return true; } bool LSEvent::IsSignaled() { return IsSignaledFromNonblockingImpl(this, this, &LSEvent::IsSignaledNonblocking); } bool LSEvent::WaitOn(AuUInt32 timeout) { return LSHandle::WaitOn(timeout); } bool LSEvent::IsSignaledNonblocking() { if (!this->atomicRelease_) { fd_set set; struct timeval tv {}; FD_ZERO(&set); FD_SET(this->handle, &set); auto active = select(this->handle + 1, &set, NULL, NULL, &tv); if (active == -1) { // todo push error return false; } return active == 1; } else { AuUInt64 oldSemaphoreValue {}; return read(this->handle, &oldSemaphoreValue, sizeof(oldSemaphoreValue)) == 8; } } ELoopSource LSEvent::GetType() { return ELoopSource::eSourceEvent; } AUKN_SYM AuSPtr NewLSEvent(bool triggered, bool atomicRelease, bool permitMultipleTriggers) { auto event = AuMakeShared(triggered, atomicRelease, permitMultipleTriggers); if (!event) { return {}; } if (!event->HasValidHandle()) { return {}; } return event; } }