UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
ExpandingChunkedList.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3/*=============================================================================
4 ExpandingChunkedList.h: Unreal realtime garbage collection internal helpers
5=============================================================================*/
6
7#pragma once
8
9#include "CoreMinimal.h"
10#include <atomic>
11#include "Misc/SpinLock.h"
12
13template<typename T, int32 NumElementsPerChunk = 64>
15{
16 struct FChunk
17 {
19 FChunk* Next = nullptr;
21 int32 NumItems = 0;
23 T Items[NumElementsPerChunk];
24 };
25
26 alignas(PLATFORM_CACHE_LINE_SIZE) mutable UE::FSpinLock Lock;
27
29 FChunk* Head = nullptr;
30
31 static void DeleteChunks(FChunk* Head)
32 {
33 for (FChunk* Chunk = Head; Chunk;)
34 {
35 FChunk* NextChunk = Chunk->Next;
36 FMemory::Free(Chunk);
37 Chunk = NextChunk;
38 }
39 }
40
41public:
42
44 {
45 Empty();
46 }
47
51 void Push(T Item)
52 {
53
54 // If we have a chunk and aren't full, then use it
55 Lock.Lock();
56 FChunk* OldHead = Head;
57 if (Head != nullptr && Head->NumItems < NumElementsPerChunk)
58 {
59 Head->Items[Head->NumItems++] = Item;
60 Lock.Unlock();
61 return;
62 }
63
64 // Outside of the lock, allocate the chunk
65 Lock.Unlock();
66 FChunk* NewChunk = new (FMemory::Malloc(sizeof(FChunk), PLATFORM_CACHE_LINE_SIZE)) FChunk();
67 Lock.Lock();
68
69 // If the head hs changed, then someone else has added a new node, try to add to that one
70 if (Head != nullptr && OldHead != Head && Head->NumItems < NumElementsPerChunk)
71 {
72 Head->Items[Head->NumItems++] = Item;
73 Lock.Unlock();
74 FMemory::Free(NewChunk); //-V611 There is no destructor and the memory came from Malloc...
75 return;
76 }
77
78 // Otherwise, we can just add out allocated node
79 NewChunk->Next = Head;
80 Head = NewChunk;
81 Head->Items[Head->NumItems++] = Item;
82 Lock.Unlock();
83 return;
84 }
85
89 FORCEINLINE bool IsEmpty() const
90 {
91 Lock.Lock();
92 bool bIsEmpty = Head == nullptr;
93 Lock.Unlock();
94 return bIsEmpty;
95 }
96
100 void Empty()
101 {
102 Lock.Lock();
103 FChunk* Current = Head;
104 Head = nullptr;
105 Lock.Unlock();
106 DeleteChunks(Current);
107 }
108
113 {
114 Lock.Lock();
115 FChunk* Current = Head;
116 Head = nullptr;
117 Lock.Unlock();
118
119 for (FChunk* Chunk = Current; Chunk; Chunk = Chunk->Next)
120 {
121 OutArray.Append(Chunk->Items, Chunk->NumItems);
122 }
123 DeleteChunks(Current);
124 }
125};
#define FORCEINLINE
Definition AndroidPlatform.h:140
FPlatformTypes::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
#define PLATFORM_CACHE_LINE_SIZE
Definition Platform.h:938
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
Definition Array.h:670
Definition ExpandingChunkedList.h:15
FORCEINLINE void PopAllAndEmpty(TArray< T > &OutArray)
Definition ExpandingChunkedList.h:112
~TExpandingChunkedList()
Definition ExpandingChunkedList.h:43
void Push(T Item)
Definition ExpandingChunkedList.h:51
FORCEINLINE bool IsEmpty() const
Definition ExpandingChunkedList.h:89
void Empty()
Definition ExpandingChunkedList.h:100
Definition SpinLock.h:15
void Unlock()
Definition SpinLock.h:42
void Lock()
Definition SpinLock.h:21
static FORCENOINLINE CORE_API void Free(void *Original)
Definition UnrealMemory.cpp:685