#pragma once #include #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 CallCount = 0; std::atomic Pause = false; }; class FCallLimiter { public: template FCallLimiter(F&& task, A&&... args) { Func = std::bind(std::forward(task), std::forward(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 Func; mutable bool NeedCall = false; float Interval = 0.0f; double LastCall = 0.0f; }; class FCallOnce { public: template FCallOnce(F&& task, A&&... args) { Processing = false; NeedCall = false; Func = std::bind(std::forward(task), std::forward(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 Callback; private: std::function Func; std::atomic_bool Processing; mutable std::atomic_bool NeedCall; };