/*** Copyright (C) 2021-2023 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: AuAsyncTimer.cpp Date: 2023-12-06 Date: 2021-11-2 Author: Reece ***/ #include #include "IAsyncRunnable.hpp" #include "AuAsyncTimer.hpp" #include "ThreadPool.hpp" namespace Aurora::Async { AsyncFuncTimer::AsyncFuncTimer(IThreadPoolInternal *owner, const AuSPtr &pCallback, const WorkerPId_t &worker, AuUInt64 uNextTickTime, AuUInt64 uInterval) : WorkItem(owner, worker, {}), uNextTickTime(uNextTickTime), uInterval(uInterval), pCallback(pCallback) { } void AsyncFuncTimer::CancelTimer() { AU_LOCK_GUARD(this->mutex); this->Cancel(); AuResetMember(this->pCallback); } AuUInt64 AsyncFuncTimer::GetLastTime() { return this->uLastTickTime; } AuUInt64 AsyncFuncTimer::GetTicks() { return this->uTickCount; } bool AsyncFuncTimer::IsCatchUp() { return this->bCatchUp; } void AsyncFuncTimer::SetCatchUp(bool bCatchUp) { this->bCatchUp = bCatchUp; } void AsyncFuncTimer::DispatchTask(IWorkItemHandler::ProcessInfo &info) { AU_LOCK_GUARD(this->mutex); info.type = ETickType::eRerun; auto uTickCount = ++this->uTickCount; this->uLastTickTime = AuTime::SteadyClockNS(); auto uDelta = this->uLastTickTime - this->uNextTickTime; this->uNextTickTime += this->uInterval; if (!this->bCatchUp) { this->uNextTickTime = AuMax(this->uNextTickTime, this->uLastTickTime); } info.reschedSteadyClockAbsNs = this->uNextTickTime; if (!this->pCallback) { return; } try { if (this->pCallback->OnTick(uTickCount, uDelta, this->uLastTickTime)) { info.type = ETickType::eSchedule; } else { info.type = ETickType::eFinished; } } catch (...) { info.type = ETickType::eSchedule; SysPushErrorCatch(); } } void AsyncFuncTimer::Cleanup() { AuResetMember(this->pCallback); } AUKN_SYM AuSPtr NewTimer(AuUInt64 uPeriodNS, const AuSPtr &pCallback, AuOptional workerPid, AuOptional uStartTime) { if (!pCallback) { SysPushErrorArg(); return {}; } if (!workerPid) { workerPid = AuAsync::GetCurrentWorkerPId(); } if (uPeriodNS < 100) { SysPushErrorArg(); return {}; } if (!uStartTime) { uStartTime = AuTime::SteadyClockNS() + uPeriodNS; } auto pThreadPool = AuStaticPointerCast(workerPid.value().GetPool()).get(); auto pRet = AuMakeShared(pThreadPool, pCallback, workerPid.value(), uStartTime.value(), uPeriodNS); if (!pRet) { return {}; } pRet->Dispatch(); return pRet; } AUKN_SYM AuSPtr NewTimer(AuUInt64 uPeriodNS, const AuSupplierConsumer &callback, AuOptional workerPid, AuOptional uStartTime) { return NewTimer(uPeriodNS, AuMakeSharedThrow(callback), workerPid, uStartTime); } }