AuroraRuntime/Source/Threading/Primitives/Event.cpp

141 lines
3.0 KiB
C++

/***
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: Event.cpp
Date: 2021-6-12
Author: Reece
***/
#include <RuntimeInternal.hpp>
#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(mutex_.get());
if (!condition_)
{
return false;
}
return true;
}
bool EventImpl::Lock(AuUInt64 timeout /*=0*/)
{
LockGuardPtr re(mutex_);
AuInt64 startTime = Aurora::Time::CurrentClockMS();
AuInt64 endTime = startTime + timeout;
while (!AtomicIsEventSet())
{
AuUInt32 timeoutMs = 0;
if (timeout)
{
timeoutMs = endTime - static_cast<AuInt64>(Aurora::Time::CurrentClockMS());
if (timeoutMs < 0)
{
return false;
}
}
if (!condition_->WaitForSignal(timeoutMs))
{
return false;
}
}
if (atomicRelease_)
{
triggered_ = false;
}
return true;
}
bool EventImpl::TryLock()
{
LockGuardPtr re(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()
{
LockGuardPtr re(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<EventImpl *>(event);
}
}