AuroraRuntime/Include/Aurora/Threading/IWaitable.hpp
Jamie Reece Wilson f08f4a476a [*] Ehhh. I never liked how I implemented the fallback for MS absolute waits.
We should calculate it via a delta between current NS time to avoid NS/MS clock overflows.
Some platforms and points in time may be more resistant than others. Let's assume monotonic time could be really high, this should help mitigate some bad math and branching caused by timeout overflows caused by stupid MS-precise abs waits (not sure why people would favour these over abs ns)
2023-09-12 17:10:51 +01:00

81 lines
2.5 KiB
C++

/***
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: IWaitable.hpp
Date: 2021-6-10
Author: Reece
***/
#pragma once
namespace Aurora::Time
{
AUKN_SYM AuUInt64 SteadyClockNS();
AUKN_SYM AuUInt64 SteadyClockMS();
}
namespace Aurora::Threading
{
/**
IWaitable represents a generic waitable primitive <br>
There is no guarantee of any specific underlying primitive or backing by the operating system directly <br>
*All* methods **must** be supported on all platforms. <br>
*/
struct AUKN_SYM IWaitable
{
// Mostly worthless. Do not access
// Used by internals
virtual bool HasOSHandle(AuMach &mach) = 0;
// Do not access
// Used by internals
virtual bool HasLockImplementation() = 0;
virtual void Lock() = 0;
inline virtual bool LockMS(AuUInt64 qwRelTimeoutInMs /* = 0, infinity - use TryLock for an opportunistic lock-spin-once operation */)
{
return this->LockAbsNS(qwRelTimeoutInMs ? Aurora::Time::SteadyClockNS() + AuMSToNS<AuUInt64>(qwRelTimeoutInMs) : 0);
}
inline virtual bool LockNS(AuUInt64 qwRelTimeoutInNs /* = 0, infinity - use TryLock for an opportunistic lock-spin-once operation */)
{
return this->LockAbsNS(qwRelTimeoutInNs ? Aurora::Time::SteadyClockNS() + qwRelTimeoutInNs : 0);
}
inline virtual bool LockAbsMS(AuUInt64 qwAbsTimeoutInMs /* = 0, infinity*/)
{
if (!qwAbsTimeoutInMs)
{
return this->LockNS(0);
}
auto iTimeMSDelta = AuInt64(qwAbsTimeoutInMs) - AuInt64(Aurora::Time::SteadyClockMS());
if (iTimeMSDelta <= 0)
{
return this->TryLock();
}
return this->LockAbsNS(AuMSToNS<AuUInt64>(iTimeMSDelta) + Aurora::Time::SteadyClockNS());
}
inline virtual bool LockAbsNS(AuUInt64 qwAbsTimeoutInNs /* = 0, infinity*/)
{
if (!qwAbsTimeoutInNs)
{
return this->LockNS(0);
}
auto iTimeDelta = AuInt64(qwAbsTimeoutInNs) - AuInt64(Aurora::Time::SteadyClockNS());
if (iTimeDelta <= 0)
{
return this->TryLock();
}
return this->LockNS(iTimeDelta);
}
virtual bool TryLock() = 0;
virtual void Unlock() = 0;
};
}