UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
EventLoopTimer.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2#pragma once
3
4#include "CoreTypes.h"
7#include "Misc/ScopeExit.h"
8#include "Misc/Timespan.h"
9#include "Stats/Stats.h"
10
11namespace UE::EventLoop {
12
14{
15 static constexpr TCHAR Name[] = TEXT("TimerHandle");
16};
17
19
21
23
24enum class ETimerStatus : uint8
25{
30 Pending,
34 Active,
47};
48
84
86{
87 static inline void CheckIsManagerThread(bool bIsManagerThread)
88 {
90 }
91};
92
93/*
94 * Default traits for timer manager. Traits are used to implement functionality which can be
95 * mocked to allow testing the class.
96 *
97 * In most cases the default traits can be used without modification.
98 */
119
131template <typename Traits = FTimerManagerDefaultTraits>
132class TTimerManager final : public FNoncopyable
133{
134public:
139
140public:
146 void Init()
147 {
148 Storage.Init();
149 }
150
158 void Tick(FTimespan DeltaTime);
159
169 {
170 if (!ActiveTimerHeap.IsEmpty())
171 {
172 FInternalHandle TopHandle = ActiveTimerHeap.HeapTop();
173 const FTimerData* TimerData = Storage.Find(TopHandle);
174 OutTimeout = TimerData->Expiration - InternalTime;
175 return true;
176 }
177
178 return false;
179 }
180
188 inline uint32 GetNumTimers() const
189 {
190 return Storage.Num();
191 }
192
206 {
207 // Callback must be set.
208 const bool bValidCallback = Callback.operator bool();
209 // Rate cannot be less than zero.
210 const bool bValidRate = InRate >= FTimespan::Zero();
211 // First delay is only valid when repeating.
212 const bool bFirstDelaySetValid = !InFirstDelay.IsSet() || InbRepeat;
213 // First delay cannot be less than zero.
214 const bool bFirstDelayValidTime = !InFirstDelay.IsSet() || (*InFirstDelay >= FTimespan::Zero());
215
217 {
218 return FTimerHandle();
219 }
220
221 return Storage.Add(FTimerData(MoveTemp(Callback), InFirstDelay, InRate, InbRepeat));
222 }
223
235 {
236 // If ClearTimer is run from the manager thread and the timer manager is currently ticking,
237 // mark the timer as pending removal so that it will not be run.
238 if (Storage.IsManagerThread() && bIsTicking)
239 {
240 if (FTimerData* TimerData = Storage.Find(InHandle))
241 {
242 TimerData->Status = ETimerStatus::PendingRemoval;
243 }
244 }
245
246 // Queue removal request.
248
249 // Invalidate the handle.
250 InHandle.Invalidate();
251 }
252
260 inline bool HasPendingRepeatTimer() const
261 {
262 return !PendingRepeatTimers.IsEmpty();
263 }
264
265private:
266 struct FTimerHeapOrder
267 {
268 explicit FTimerHeapOrder(const FStorageType& InStorage)
269 : Storage(InStorage)
270 , NumTimers(InStorage.Num())
271 {
272 }
273
274 bool operator()(FInternalHandle LhsHandle, FInternalHandle RhsHandle) const
275 {
276 const FTimerData* LhsData = Storage.Find(LhsHandle);
277 const FTimerData* RhsData = Storage.Find(RhsHandle);
278
279 // Move to top if empty.
280 if (LhsData == nullptr)
281 {
282 return true;
283 }
284
285 // Move to top if empty.
286 if (RhsData == nullptr)
287 {
288 return false;
289 }
290
291 return LhsData->Expiration < RhsData->Expiration;
292 }
293
294 const FStorageType& Storage;
295 int32 NumTimers;
296 };
297
299 FStorageType Storage;
305 FTimespan InternalTime;
307 bool bIsTicking = false;
308};
309
310template <typename Traits>
312{
314
315 Traits::CheckIsManagerThread(Storage.IsManagerThread());
316
317 bIsTicking = true;
318 ON_SCOPE_EXIT{ bIsTicking = false; };
319
320 // Progress internal time.
321 InternalTime += DeltaTime;
322
323 // Process queued actions.
326 Storage.Update(&AddedHandles, &RemovedHandles);
327
328 {
330
331 // Activate new timers.
332 // Timers are always added on the next call to Tick regardless of thread to provide the
333 // guarantee that a timer may fire late, but never early.
334 for (FInternalHandle InternalHandle : AddedHandles)
335 {
336 // Timer data may not be found if the timer was added and removed before Tick was called.
337 if (FTimerData* TimerData = Storage.Find(InternalHandle))
338 {
339 const FTimespan EffectiveInitialRate = TimerData->FirstDelay ? *TimerData->FirstDelay : TimerData->Rate;
340 TimerData->Expiration = InternalTime + EffectiveInitialRate;
341 TimerData->Status = ETimerStatus::Active;
342 ActiveTimerHeap.HeapPush(InternalHandle, FTimerHeapOrder(Storage));
343 }
344 }
345 }
346
347 {
349
350 // Clear removed timers.
351 for (FInternalHandle InternalHandle : RemovedHandles)
352 {
353 // Index may not be found if the timer was added and removed before Tick was called.
354 int32 InternalHandleIndex = ActiveTimerHeap.Find(InternalHandle);
356 {
357 ActiveTimerHeap.HeapRemoveAt(InternalHandleIndex, FTimerHeapOrder(Storage), EAllowShrinking::No);
358 }
359 }
360 }
361
362 {
364
365 // Schedule timers waiting to be repeated.
366 for (FInternalHandle InternalHandle : PendingRepeatTimers)
367 {
368 // Index may not be found if the timer was removed before Tick was called.
369 if (FTimerData* TimerData = Storage.Find(InternalHandle))
370 {
371 TimerData->Expiration = InternalTime + TimerData->Rate;
372 TimerData->Status = ETimerStatus::Active;
373 ActiveTimerHeap.HeapPush(InternalHandle, FTimerHeapOrder(Storage));
374 }
375 }
376 PendingRepeatTimers.Empty();
377 }
378
379 {
381
382 while (ActiveTimerHeap.Num() > 0)
383 {
384 FInternalHandle TopHandle = ActiveTimerHeap.HeapTop();
385 FTimerData* TimerData = Storage.Find(TopHandle);
386
387 // TimerHeap is now resolved with Storage. All entries are valid.
388 check(TimerData);
389
390 // Pop from heap and continue if timer was removed during iteration.
391 // The timer data will be removed on the next call to Update.
392 if (TimerData->Status == ETimerStatus::PendingRemoval)
393 {
394 FInternalHandle TimerHandle;
395 ActiveTimerHeap.HeapPop(TimerHandle, FTimerHeapOrder(Storage), EAllowShrinking::No);
396 continue;
397 }
398
399 if (InternalTime >= TimerData->Expiration)
400 {
401 FInternalHandle TimerHandle;
402 ActiveTimerHeap.HeapPop(TimerHandle, FTimerHeapOrder(Storage), EAllowShrinking::No);
403
404 // Fire user timer callback.
405 TimerData->Status = ETimerStatus::Executing;
406 TimerData->Callback();
407
408 // Reschedule repeating timers.
409 if (TimerData->bRepeat)
410 {
412 PendingRepeatTimers.Add(TimerHandle);
413 }
414 else
415 {
416 // Timer has been fired and is non-repeating. Remove the timer.
417 Storage.Remove(TopHandle);
418 }
419 }
420 else
421 {
422 break;
423 }
424 }
425 }
426}
427
428/* UE::EventLoop */ }
OODEFFUNC typedef void(OODLE_CALLBACK t_fp_OodleCore_Plugin_Free)(void *ptr)
#define check(expr)
Definition AssertionMacros.h:314
@ INDEX_NONE
Definition CoreMiscDefines.h:150
#define TEXT(x)
Definition Platform.h:1272
FPlatformTypes::TCHAR TCHAR
Either ANSICHAR or WIDECHAR, depending on whether the platform supports wide characters or the requir...
Definition Platform.h:1135
FPlatformTypes::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
#define QUICK_SCOPE_CYCLE_COUNTER(Stat)
Definition Stats.h:652
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
@ Num
Definition MetalRHIPrivate.h:234
const bool
Definition NetworkReplayStreaming.h:178
#define ON_SCOPE_EXIT
Definition ScopeExit.h:73
UE_INTRINSIC_CAST UE_REWRITE constexpr std::remove_reference_t< T > && MoveTemp(T &&Obj) noexcept
Definition UnrealTemplate.h:520
uint8_t uint8
Definition binka_ue_file_header.h:8
uint32_t uint32
Definition binka_ue_file_header.h:6
Definition UnrealTemplate.h:321
Definition Array.h:670
UE_REWRITE bool IsEmpty() const
Definition Array.h:1133
UE_NODEBUG const ElementType & HeapTop() const UE_LIFETIMEBOUND
Definition Array.h:3848
Definition ContainerAllocationPolicies.h:894
TManagedStorageInternalHandle< FExternalHandle > FInternalHandle
Definition EventLoopManagedStorage.h:159
ElementType * Find(FExternalHandle Handle)
Definition EventLoopManagedStorage.h:352
typename Traits::FExternalHandle FExternalHandle
Definition EventLoopManagedStorage.h:158
bool IsManagerThread() const
Definition EventLoopManagedStorage.h:214
TArray< FInternalHandle, typename Traits::InternalHandleArryAllocatorType > FInternalHandleArryType
Definition EventLoopManagedStorage.h:160
void Init()
Definition EventLoopManagedStorage.h:224
void Remove(const FExternalHandle Handle, FManagedStorageOnRemoveComplete &&OnRemoveComplete=FManagedStorageOnRemoveComplete())
Definition EventLoopManagedStorage.h:316
FExternalHandle Add(ElementType &&Data)
Definition EventLoopManagedStorage.h:300
int32 Num() const
Definition EventLoopManagedStorage.h:340
Definition EventLoopTimer.h:133
void Init()
Definition EventLoopTimer.h:146
bool GetNextTimeout(FTimespan &OutTimeout) const
Definition EventLoopTimer.h:168
typename FStorageType::FInternalHandle FInternalHandle
Definition EventLoopTimer.h:137
TManagedStorage< FTimerData, typename Traits::FStorageTraits > FStorageType
Definition EventLoopTimer.h:135
FTimerHandle SetTimer(FTimerCallback &&Callback, FTimespan InRate, bool InbRepeat=false, TOptional< FTimespan > InFirstDelay=TOptional< FTimespan >())
Definition EventLoopTimer.h:205
bool HasPendingRepeatTimer() const
Definition EventLoopTimer.h:260
void Tick(FTimespan DeltaTime)
Definition EventLoopTimer.h:311
typename FStorageType::FInternalHandleArryType FInternalHandleArryType
Definition EventLoopTimer.h:138
uint32 GetNumTimers() const
Definition EventLoopTimer.h:188
void ClearTimer(FTimerHandle &InHandle, FOnTimerCleared &&OnTimerCleared=FOnTimerCleared())
Definition EventLoopTimer.h:234
typename FStorageType::FExternalHandle FTimerHandle
Definition EventLoopTimer.h:136
Definition EventLoopLog.cpp:5
TUniqueFunction< void()> FManagedStorageOnRemoveComplete
Definition EventLoopManagedStorage.h:17
TResourceHandle< FTimerHandleTraits > FTimerHandle
Definition EventLoopTimer.h:22
ETimerStatus
Definition EventLoopTimer.h:25
FManagedStorageOnRemoveComplete FOnTimerCleared
Definition EventLoopTimer.h:20
Definition TimerManager.h:73
Definition TimerHandle.h:12
Definition TimerManager.cpp:253
Definition Timespan.h:76
static FTimespan Zero()
Definition Timespan.h:747
Definition Optional.h:131
Definition EventLoopManagedStorage.h:54
Definition EventLoopTimer.h:50
ETimerStatus Status
Definition EventLoopTimer.h:71
FTimerData(FTimerData &&)=default
uint8 bRepeat
Definition EventLoopTimer.h:74
FTimerData & operator=(const FTimerData &)=delete
FTimespan Expiration
Definition EventLoopTimer.h:69
FTimerData & operator=(FTimerData &&)=default
TOptional< FTimespan > FirstDelay
Definition EventLoopTimer.h:63
FTimerCallback Callback
Definition EventLoopTimer.h:60
FTimerData(const FTimerData &)=delete
FTimespan Rate
Definition EventLoopTimer.h:66
FTimerData(FTimerCallback &&InCallback, TOptional< FTimespan > InFirstDelay, FTimespan InRate, bool bInRepeat)
Definition EventLoopTimer.h:51
Definition EventLoopTimer.h:14
static constexpr TCHAR Name[]
Definition EventLoopTimer.h:15
Definition EventLoopTimer.h:100
Definition EventLoopTimer.h:86
static void CheckIsManagerThread(bool bIsManagerThread)
Definition EventLoopTimer.h:87
Definition EventLoopHandle.h:12