213 lines
3.1 KiB
C++
213 lines
3.1 KiB
C++
#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;
|
||
};
|
||
|
||
|