/*** Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: Event.cpp Date: 2021-6-12 Author: Reece ***/ #include #include "Event.hpp" namespace Aurora::Threading::Primitives { EventImpl::EventImpl(bool trigged, bool atomicRelease, bool permitMultipleTriggers) : triggered_(trigged), atomicRelease_(atomicRelease), permitMultipleTriggers_(permitMultipleTriggers) {} EventImpl::~EventImpl() {} bool EventImpl::Init() { mutex_ = ConditionMutexUnique(); if (!mutex_) { return false; } condition_ = ConditionVariableUnique(AuUnsafeRaiiToShared(mutex_)); if (!condition_) { return false; } return true; } bool EventImpl::Lock(AuUInt64 timeout /*=0*/) { AU_LOCK_GUARD(mutex_); AuInt64 startTime = Aurora::Time::CurrentClockMS(); AuInt64 endTime = startTime + timeout; while (!AtomicIsEventSet()) { AuUInt32 timeoutMs = 0; if (timeout) { timeoutMs = endTime - static_cast(Aurora::Time::CurrentClockMS()); if (timeoutMs < 0) { return false; } } if (!condition_->WaitForSignal(timeoutMs)) { return false; } } if (atomicRelease_) { triggered_ = false; } return true; } bool EventImpl::TryLock() { AU_LOCK_GUARD(mutex_); return AtomicIsEventSet(); } bool EventImpl::AtomicIsEventSet() { if (!triggered_) return false; if (atomicRelease_) triggered_ = false; return true; } void EventImpl::Reset() { mutex_->Lock(); triggered_ = false; mutex_->Unlock(); } void EventImpl::Set() { AU_LOCK_GUARD(mutex_); SysAssertExp((permitMultipleTriggers_) || (!triggered_), "Can not trigger an awake event object"); triggered_ = true; condition_->Broadcast(); } bool EventImpl::HasOSHandle(AuMach &mach) { mach = 0; return false; } bool EventImpl::HasLockImplementation() { return true; } void EventImpl::Lock() { auto ok = Lock(0); SysAssert(ok); } void EventImpl::Unlock() { // Unlike the other types, unlock is ways a nop } AUKN_SYM IEvent *EventNew(bool trigged, bool atomicRelease, bool permitMultipleTriggers) { auto event = _new EventImpl(trigged, atomicRelease, permitMultipleTriggers); if (!event) { return nullptr; } if (!event->Init()) { EventRelease(event); return nullptr; } return event; } AUKN_SYM void EventRelease(IEvent *event) { SafeDelete(event); } }