/*** Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: Event.cpp Date: 2021-6-12 Author: Reece ***/ #include #include "AuEvent.hpp" #include "SMTYield.hpp" namespace Aurora::Threading::Primitives { EventImpl::EventImpl(bool bTriggered, bool bAtomicRelease, bool bPermitMultipleTriggers) : bTriggered_(bTriggered), bAtomicRelease_(bAtomicRelease), bPermitMultipleTriggers_(bPermitMultipleTriggers), condition_(AuUnsafeRaiiToShared(&this->mutex_)) {} EventImpl::~EventImpl() {} bool EventImpl::Init() { return true; } bool EventImpl::LockMS(AuUInt64 uTimeout /*=0*/) { return LockNS(AuMSToNS(uTimeout)); } bool EventImpl::LockNS(AuUInt64 uTimeout /*=0*/) { AU_LOCK_GUARD(this->mutex_); AuInt64 uStartTime = Time::SteadyClockNS(); AuInt64 uEndTime = uStartTime + uTimeout; while (!AtomicIsEventSetLogic()) { AuUInt32 uTimeoutNS {}; if (uTimeout) { uStartTime = Time::SteadyClockNS(); if (uStartTime >= uEndTime) { return false; } uTimeoutNS = uEndTime - uStartTime; } if (!this->condition_.WaitForSignalNS(uTimeoutNS)) { continue; } } if (this->bAtomicRelease_) { this->bTriggered_ = false; } return true; } bool EventImpl::TryLock() { AU_LOCK_GUARD(this->mutex_); return AtomicIsEventSetLogic(); } bool EventImpl::AtomicIsEventSetLogic() { if (!this->bTriggered_) { return false; } if (this->bAtomicRelease_) { this->bTriggered_ = false; } return true; } void EventImpl::Reset() { this->mutex_.Lock(); this->bTriggered_ = false; this->mutex_.Unlock(); } void EventImpl::Set() { AU_LOCK_GUARD(this->mutex_); SysAssertExp((this->bPermitMultipleTriggers_) || (!this->bTriggered_), "Can not trigger an awake event object"); this->bTriggered_ = true; this->condition_.Broadcast(); } bool EventImpl::HasOSHandle(AuMach &mach) { mach = 0; return false; } bool EventImpl::HasLockImplementation() { return true; } void EventImpl::Lock() { auto ok = LockNS(0); SysAssert(ok); } void EventImpl::Unlock() { // Unlock is always a NOP; inverse of a lock/wait is nothing } AUKN_SYM IEvent *EventNew(bool bTriggered, bool bAtomicRelease, bool bPermitMultipleTriggers) { auto event = _new EventImpl(bTriggered, bAtomicRelease, bPermitMultipleTriggers); if (!event) { return nullptr; } if (!event->Init()) { EventRelease(event); return nullptr; } return event; } AUKN_SYM void EventRelease(IEvent *pEvent) { AuSafeDelete(pEvent); } AUROXTL_INTERFACE_SOO_SRC_EX(AURORA_SYMBOL_EXPORT, Event, EventImpl, (bool, bTriggered), (bool, bAtomicRelease), (bool, bPermitMultipleTriggers)) }