AuroraRuntime/Source/Threading/Primitives/AuEvent.cpp
Reece e82ec4a343 [+] IWaitable::LockNS(...)
[+] AuThreading.WakeAllOnAddress
[+] AuThreading.WakeOnAddress
[+] AuThreading.WakeNOnAddress
[+] AuThreading.TryWaitOnAddress
[+] AuThreading.WaitOnAddress
[*] Further optimize synch primitives
[+] AuThreadPrimitives::RWRenterableLock
2023-03-12 15:27:28 +00:00

151 lines
3.3 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 <Source/RuntimeInternal.hpp>
#include "AuEvent.hpp"
#include "SMPYield.hpp"
namespace Aurora::Threading::Primitives
{
EventImpl::EventImpl(bool bTriggered, bool bAtomicRelease, bool bPermitMultipleTriggers) :
triggered_(bTriggered),
atomicRelease_(bAtomicRelease),
permitMultipleTriggers_(bPermitMultipleTriggers),
condition_(AuUnsafeRaiiToShared(&this->mutex_))
{}
EventImpl::~EventImpl() {}
bool EventImpl::Init()
{
return true;
}
bool EventImpl::Lock(AuUInt64 timeout /*=0*/)
{
return LockNS(AuMSToNS<AuUInt64>(timeout));
}
bool EventImpl::LockNS(AuUInt64 timeout /*=0*/)
{
AU_LOCK_GUARD(this->mutex_);
AuInt64 uStartTime = Time::SteadyClockNS();
AuInt64 uEndTime = uStartTime + timeout;
while (!AtomicIsEventSet())
{
AuUInt32 uTimeoutMs {};
if (timeout)
{
uStartTime = Time::SteadyClockNS();
if (uStartTime >= uEndTime)
{
return false;
}
uTimeoutMs = AuNSToMS<AuUInt64>(uEndTime - uStartTime);
if (!uTimeoutMs)
{
this->mutex_.Unlock();
SMPPause();
AuThreading::ContextYield();
this->mutex_.Lock();
continue;
}
}
if (!this->condition_.WaitForSignal(uTimeoutMs))
{
continue;
}
}
if (this->atomicRelease_)
{
this->triggered_ = false;
}
return true;
}
bool EventImpl::TryLock()
{
AU_LOCK_GUARD(mutex_);
return AtomicIsEventSet();
}
bool EventImpl::AtomicIsEventSet()
{
if (!this->triggered_) return false;
if (this->atomicRelease_) this->triggered_ = false;
return true;
}
void EventImpl::Reset()
{
this->mutex_.Lock();
this->triggered_ = false;
this->mutex_.Unlock();
}
void EventImpl::Set()
{
AU_LOCK_GUARD(this->mutex_);
SysAssertExp((this->permitMultipleTriggers_) || (!this->triggered_), "Can not trigger an awake event object");
this->triggered_ = true;
this->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 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<EventImpl *>(pEvent);
}
}