UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
LinearBlockAllocator.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#include "Containers/Array.h"
6#include "CoreTypes.h"
8#include "HAL/UnrealMemory.h"
10#include "Misc/ScopeLock.h"
11
12#include <atomic>
13
15{
16
17struct FBlock
18{
20};
21
22}
23namespace UE { class FLinearBlockAllocatorThreadAccessor; }
24
25namespace UE
26{
27
44{
45public:
47
48 void* Malloc(SIZE_T Size, uint32 Alignment);
49
50private:
51 void* TryAllocateFromBlock(SIZE_T Size, uint32 Alignment, UE::LinearBlockAllocator::Private::FBlock* Block);
52 bool RequiresCustomAllocation(SIZE_T Size, uint32 Alignment) const;
54 void* GetCustomAllocation(SIZE_T Size, uint32 Alignment);
55
56 TArray<void*> BlockAllocs; // guarded by LockForThreadSafeAllocator when threading
57 UE::LinearBlockAllocator::Private::FBlock* LastBlock = nullptr; // unused during threading
58 uint32 BlockAlignment = 4; // constant during threading
59 SIZE_T BlockSize = 1 << 16; // constant during threading
60 FCriticalSection LockForThreadSafeAllocator;
61 std::atomic<int32> ReferenceCount{ 0 };
62
64};
65
90
91} // namespace UE
92
93
95// Inline implementations
97
98
99namespace UE
100{
101
103{
104 using namespace UE::LinearBlockAllocator::Private;
105
106 checkf(ReferenceCount.load(std::memory_order_relaxed) == 0,
107 TEXT("FLinearBlockAllocator is destroyed while still in use by a FLinearBlockAllocatorThreadAccessor."));
108 for (void* BlockAlloc : BlockAllocs)
109 {
111 }
112}
113
115{
116 checkf(ReferenceCount.load(std::memory_order_relaxed) == 0,
117 TEXT("FLinearBlockAllocator::Malloc is being used directly while in use by a FLinearBlockAllocatorThreadAccessor, this is not allowed, all malloc calls must go through a FLinearBlockAllocatorThreadAccessor."));
118
119 void* Result = TryAllocateFromBlock(Size, Alignment, LastBlock);
120 if (Result)
121 {
122 return Result;
123 }
124
125 if (RequiresCustomAllocation(Size, Alignment))
126 {
127 return GetCustomAllocation(Size, Alignment);
128 }
129
130 LastBlock = GetNewBlock();
131 Result = TryAllocateFromBlock(Size, Alignment, LastBlock);
132 check(Result);
133 return Result;
134}
135
136inline void* FLinearBlockAllocator::TryAllocateFromBlock(SIZE_T Size, uint32 Alignment,
138{
139 if (!Block)
140 {
141 return nullptr;
142 }
143
144 void* NextPtr = (void*)(((SIZE_T)Block) + ((SIZE_T)Block->NextOffset));
145 void* AlignedPtr = Align(NextPtr, Alignment);
146 SIZE_T NewOffset = ((SIZE_T)AlignedPtr) + Size - ((SIZE_T)Block);
147 if (NewOffset > BlockSize)
148 {
149 return nullptr;
150 }
151
152 Block->NextOffset = (int32)NewOffset;
153 return AlignedPtr;
154}
155
156bool FLinearBlockAllocator::RequiresCustomAllocation(SIZE_T Size, uint32 Alignment) const
157{
158 using namespace UE::LinearBlockAllocator::Private;
159
160 // Compute the worse case AlignmentPadding, which occurs if the pointer we received for the block allocation
161 // is aligned to BlockAlignment and nothing higher, which we can calculate by assuming the pointer starts at
162 // 1*BlockAlignment. The starting position is then BlockHeaderSize after that, and we have to AlignUp the
163 // starting position.
164 constexpr uint32 BlockHeaderSize = sizeof(FBlock);
165 uint32 StartingOffset = BlockAlignment + BlockHeaderSize;
166 uint32 AlignedOffset = Align(StartingOffset, Alignment);
167 uint32 AlignmentPadding = AlignedOffset - StartingOffset;
168 SIZE_T RequiredBlockSize = Size + AlignmentPadding + BlockHeaderSize;
169 return RequiredBlockSize > BlockSize;
170}
171
172UE::LinearBlockAllocator::Private::FBlock* FLinearBlockAllocator::GetNewBlock()
173{
174 using namespace UE::LinearBlockAllocator::Private;
175
176 constexpr uint32 BlockHeaderSize = sizeof(FBlock);
177 void* BlockAllocation = FMemory::Malloc(BlockSize, BlockAlignment);
178 FBlock* NewBlock = reinterpret_cast<FBlock*>(BlockAllocation);
180 BlockAllocs.Add(BlockAllocation);
181 return NewBlock;
182}
183
184void* FLinearBlockAllocator::GetCustomAllocation(SIZE_T Size, uint32 Alignment)
185{
186 using namespace UE::LinearBlockAllocator::Private;
187
188 void* CustomAllocation = FMemory::Malloc(Size, Alignment);
189 BlockAllocs.Add(CustomAllocation);
190 return CustomAllocation;
191}
192
195{
196 Allocator.ReferenceCount.fetch_add(1, std::memory_order_relaxed);
197}
198
200{
201 Allocator.ReferenceCount.fetch_add(-1, std::memory_order_relaxed);
202}
203
205{
206 void* Result = Allocator.TryAllocateFromBlock(Size, Alignment, LastBlock);
207 if (Result)
208 {
209 return Result;
210 }
211
212 {
213 FScopeLock ScopeLockForThreadSafeAllocator(&Allocator.LockForThreadSafeAllocator);
214 if (Allocator.RequiresCustomAllocation(Size, Alignment))
215 {
216 return Allocator.GetCustomAllocation(Size, Alignment);
217 }
218 LastBlock = Allocator.GetNewBlock();
219 }
220 Result = Allocator.TryAllocateFromBlock(Size, Alignment, LastBlock);
221 check(Result);
222 return Result;
223}
224
225} // namespace UE
constexpr T Align(T Val, uint64 Alignment)
Definition AlignmentTemplates.h:18
#define check(expr)
Definition AssertionMacros.h:314
#define checkf(expr, format,...)
Definition AssertionMacros.h:315
#define TEXT(x)
Definition Platform.h:1272
FPlatformTypes::SIZE_T SIZE_T
An unsigned integer the same size as a pointer, the same as UPTRINT.
Definition Platform.h:1150
FPlatformTypes::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
UE::FPlatformRecursiveMutex FCriticalSection
Definition CriticalSection.h:53
uint32 Size
Definition VulkanMemory.cpp:4034
uint32_t uint32
Definition binka_ue_file_header.h:6
Definition ScopeLock.h:141
Definition Array.h:670
UE_NODEBUG UE_FORCEINLINE_HINT SizeType Add(ElementType &&Item)
Definition Array.h:2696
Definition LinearBlockAllocator.h:79
~FLinearBlockAllocatorThreadAccessor()
Definition LinearBlockAllocator.h:199
void * Malloc(SIZE_T Size, uint32 Alignment)
Definition LinearBlockAllocator.h:204
FLinearBlockAllocatorThreadAccessor(FLinearBlockAllocator &InAllocator)
Definition LinearBlockAllocator.h:193
Definition LinearBlockAllocator.h:44
~FLinearBlockAllocator()
Definition LinearBlockAllocator.h:102
void * Malloc(SIZE_T Size, uint32 Alignment)
Definition LinearBlockAllocator.h:114
Definition LinearBlockAllocator.h:15
Definition AdvancedWidgetsModule.cpp:13
static FORCENOINLINE CORE_API void Free(void *Original)
Definition UnrealMemory.cpp:685
Definition LinearBlockAllocator.h:18
int32 NextOffset
Definition LinearBlockAllocator.h:19