/*** Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: RateLimiter.hpp Date: 2022-2-8 Author: Reece ***/ #pragma once namespace Aurora::Utility { struct RateLimiter { AuUInt64 nextTriggerTime {}; AuUInt64 nsTimeStep {}; bool noCatchUp {}; inline RateLimiter() { } inline RateLimiter(AuUInt64 nsTimeStep) { SetNextStep(nsTimeStep); } inline auline void SetTargetTime(AuUInt64 timeAbsNs) { this->nsTimeStep = 0; this->nextTriggerTime = timeAbsNs; } inline auline void SetNextStep(AuUInt64 nsTimeStep) { this->nsTimeStep = nsTimeStep; this->nextTriggerTime = nsTimeStep + Aurora::Time::SteadyClockNS(); } inline auline bool CheckExchangePass() { auto cur = this->nextTriggerTime; if (!cur) { return false; } if (cur <= Aurora::Time::SteadyClockNS()) { if (this->nsTimeStep) { return AuAtomicCompareExchange(&this->nextTriggerTime, GetLatch(), cur) == cur; } else { return true; } } return false; } inline auline bool HasPassed() { if (!this->nextTriggerTime) { return false; } if (this->nextTriggerTime <= Aurora::Time::SteadyClockNS()) { return true; } return false; } inline auline void Relatch() { if (this->nsTimeStep) { AuAtomicAdd(&this->nextTriggerTime, GetLatch()); } } private: inline auline AuUInt64 GetLatch() { if (this->noCatchUp) { return this->nsTimeStep + Aurora::Time::SteadyClockNS(); } else { return this->nextTriggerTime + this->nsTimeStep; } } }; };