154 lines
4.1 KiB
C++
154 lines
4.1 KiB
C++
/***
|
|
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 <Source/RuntimeInternal.hpp>
|
|
#include "IAsyncRunnable.hpp"
|
|
#include "AuAsyncTimer.hpp"
|
|
#include "ThreadPool.hpp"
|
|
|
|
namespace Aurora::Async
|
|
{
|
|
AsyncFuncTimer::AsyncFuncTimer(IThreadPoolInternal *owner,
|
|
const AuSPtr<IAsyncTimerCallback> &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<IAsyncTimer> NewTimer(AuUInt64 uPeriodNS,
|
|
const AuSPtr<IAsyncTimerCallback> &pCallback,
|
|
AuOptional<WorkerPId_t> workerPid,
|
|
AuOptional<AuUInt64> uStartTime)
|
|
{
|
|
if (!pCallback)
|
|
{
|
|
SysPushErrorArg();
|
|
return {};
|
|
}
|
|
|
|
if (!workerPid)
|
|
{
|
|
workerPid = AuAsync::GetCurrentWorkerPId();
|
|
}
|
|
|
|
if (uPeriodNS < 100)
|
|
{
|
|
SysPushErrorArg();
|
|
return {};
|
|
}
|
|
|
|
if (!uStartTime)
|
|
{
|
|
uStartTime = AuTime::SteadyClockNS() + uPeriodNS;
|
|
}
|
|
|
|
auto pThreadPool = AuStaticPointerCast<ThreadPool>(workerPid.value().GetPool()).get();
|
|
auto pRet = AuMakeShared<AsyncFuncTimer>(pThreadPool,
|
|
pCallback,
|
|
workerPid.value(),
|
|
uStartTime.value(),
|
|
uPeriodNS);
|
|
if (!pRet)
|
|
{
|
|
return {};
|
|
}
|
|
|
|
pRet->Dispatch();
|
|
return pRet;
|
|
}
|
|
|
|
AUKN_SYM AuSPtr<IAsyncTimer> NewTimer(AuUInt64 uPeriodNS,
|
|
const AuSupplierConsumer<bool, AuUInt64, AuUInt64, AuUInt64> &callback,
|
|
AuOptional<WorkerPId_t> workerPid,
|
|
AuOptional<AuUInt64> uStartTime)
|
|
{
|
|
return NewTimer(uPeriodNS,
|
|
AuMakeSharedThrow<IAsyncTimerCallbackFunctional>(callback),
|
|
workerPid,
|
|
uStartTime);
|
|
}
|
|
} |