AronaSlate/Source/AronaCore/Misc/CallRateLimiter.h
2024-01-25 11:21:15 +08:00

213 lines
3.1 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#pragma once
#include <functional>
#include "App.h"
#include "Singleton/CallRateLimiterManager.h"
#include "HAL/PlatformTime.h"
class FCallRateLimiter
{
public:
FCallRateLimiter()
{
CallRate = 0.1f;
}
FCallRateLimiter(float InCallRate, FSimpleDelegate InFuncDelegate)
: CallRate(InCallRate)
, FuncDelegate(InFuncDelegate)
{
}
void Call()
{
const double Now = FPlatformTime::Seconds();
if (Now - LastCallTime > CallRate)
{
LastCallTime = Now;
FuncDelegate.ExecuteIfBound();
}
}
void SetCallRate(float InCallRate)
{
CallRate = InCallRate;
}
FSimpleDelegate& GetFuncDelegate()
{
return FuncDelegate;
}
private:
float CallRate;
FSimpleDelegate FuncDelegate;
double LastCallTime = 0;
};
// 如果在执行过程中又调用了Call那么会在执行完毕后立即执行一次的版本
class FDelayCaller
{
public:
FDelayCaller(): Timer(0)
{
CallRate = 0.1f;
}
FDelayCaller(float InCallRate, FSimpleDelegate InFuncDelegate)
: CallRate(InCallRate)
, FuncDelegate(InFuncDelegate)
, Timer(0)
{
}
~FDelayCaller()
{
}
void Tick(float DeltaTime)
{
if (CallCount == 0)
return;
Timer -= DeltaTime;
if (Timer > 0)
return;
if (Pause)
return;
Timer = 0;
FuncDelegate.ExecuteIfBound();
if (CallCount > 0)
{
Timer = CallRate;
CallCount = 0;
}
}
void Call()
{
++CallCount;
Timer = CallRate;
}
void ConstCall() const
{
++CallCount;
Timer = CallRate;
}
void SetPause(bool InPause)
{
Pause = InPause;
}
void SetCallRate(float InCallRate)
{
CallRate = InCallRate;
}
FSimpleDelegate& GetFuncDelegate()
{
return FuncDelegate;
}
private:
float CallRate;
FSimpleDelegate FuncDelegate;
double LastCallTime = 0;
mutable float Timer;
mutable std::atomic<int32> CallCount = 0;
std::atomic<bool> Pause = false;
};
class FCallLimiter
{
public:
template <typename F, typename... A>
FCallLimiter(F&& task, A&&... args)
{
Func = std::bind(std::forward<F>(task), std::forward<A>(args)...);
}
void SetInterval(float interval)
{
Interval = interval;
}
void Update()
{
const double CurrentTime = FApp::GetCurrentTime();
if (NeedCall && CurrentTime - LastCall > Interval)
{
Func();
LastCall = CurrentTime;
NeedCall = false;
}
}
void Call()
{
NeedCall = true;
}
void Call() const
{
NeedCall = true;
}
private:
TFunction<void()> Func;
mutable bool NeedCall = false;
float Interval = 0.0f;
double LastCall = 0.0f;
};
class FCallOnce
{
public:
template <typename F, typename... A>
FCallOnce(F&& task, A&&... args)
{
Processing = false;
NeedCall = false;
Func = std::bind(std::forward<F>(task), std::forward<A>(args)...);
FCallRateLimiterManager::Get().Add(this);
}
void Call()
{
NeedCall = true;
}
void Call() const
{
NeedCall = true;
}
void Reset()
{
Processing = false;
}
void Update()
{
if (NeedCall && !Processing)
{
Processing = true;
NeedCall = false;
Func();
if (Callback)
{
Callback();
}
}
}
std::function<void()> Callback;
private:
std::function<void()> Func;
std::atomic_bool Processing;
mutable std::atomic_bool NeedCall;
};