UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
NetSerializerArrayStorage.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#include "HAL/Platform.h"
6#include "Iris/IrisConfig.h"
10
11namespace UE::Net
12{
13
14namespace AllocationPolicies
15{
16
21{
22public:
24
25 template<typename ElementType>
27 {
28 public:
29 ForElementType() : Data(nullptr) {}
30
31 ~ForElementType() { checkf(Data == nullptr, TEXT("Data allocated for dynamic states must be explictly freed")); }
32
33 ElementType* GetAllocation() const { return Data; }
34
35 void Initialize() { Data = nullptr; }
36
38
39 SizeType CalculateNewCapacity(SizeType NumElements) const { return NumElements; }
40
41 bool HasAllocation() const { return !!Data; }
42
43 SizeType GetInitialCapacity() const { return 0; }
44
45 private:
46
48 ForElementType& operator=(const ForElementType&);
49
50 ElementType* Data;
51 };
52
53private:
54
55 static IRISCORE_API void Free(FNetSerializationContext& Context, void* Ptr);
56 static IRISCORE_API void* Realloc(FNetSerializationContext& Context, void* Original, SIZE_T Size, uint32 Alignment);
57};
58
63template <uint32 NumInlineElements, typename SecondaryAllocator = FElementAllocationPolicy>
65{
66public:
67 using SizeType = typename SecondaryAllocator::SizeType;
68
69 template<typename ElementType>
71 {
72 public:
73
75
76 ElementType* GetAllocation() const
77 {
78 if (ElementType* Result = SecondaryData.GetAllocation())
79 {
80 return Result;
81 }
82 return GetInlineElements();
83 }
84
85 void Initialize() { SecondaryData.Initialize(); }
86
88
89 SizeType CalculateNewCapacity(SizeType NumElements) const;
90
91 bool HasAllocation() const { return SecondaryData.HasAllocation(); }
92
93 SizeType GetInitialCapacity() const { return NumInlineElements; }
94
95 private:
97 ForElementType& operator=(const ForElementType&);
98
100 TTypeCompatibleBytes<ElementType> InlineData[NumInlineElements];
101
103 typename SecondaryAllocator::template ForElementType<ElementType> SecondaryData;
104
106 ElementType* GetInlineElements() const { return (ElementType*)InlineData; }
107 };
108};
109
110}
111
118template <typename QuantizedElementType, typename AllocationPolicy = AllocationPolicies::FElementAllocationPolicy>
120{
121public:
122 // Verify that type is pod and trivially copyable
123 static_assert(TIsPODType<QuantizedElementType>::Value, "Only pod types are supported by FNetSerializerArrayHelper");
124 static_assert(TIsTriviallyCopyAssignable<QuantizedElementType>::Value, "Only types are triviallyCopyAssignable is supported by FNetSerializerArrayHelper");
125
128
129 typedef typename AllocationPolicy::template ForElementType<ElementType> ElementAllocatorType;
130 typedef typename AllocationPolicy::SizeType SizeType;
131
132public:
133
138
144
151
158 inline void Clone(FNetSerializationContext& Context, const ArrayType& Source);
159
160 const ElementType* GetData() const { return AllocatorInstance.GetAllocation(); }
161 ElementType* GetData() { return AllocatorInstance.GetAllocation(); }
162 SizeType Num() const { return ArrayNum; }
163
164private:
165 ElementAllocatorType AllocatorInstance;
166 SizeType ArrayNum;
167 SizeType ArrayMaxCapacity;
168};
169
178{
179public:
180 // Use whatever SizeType that is typically used by FNetSerializerArrayStorage
182
183public:
189
196
204
205 inline const uint8* GetData() const;
206 inline uint8* GetData();
207 inline SizeType Num() const;
208 inline SizeType GetAlignment() const;
209
210private:
211 uint8* Data = nullptr;
212 SizeType StorageNum = 0;
213 SizeType StorageMaxCapacity = 0;
214 // An alignment of 0 isn't valid but the value is only used if there's actual data involved.
215 SizeType StorageAlignment = 0;
216};
217
218// FNetSerializerArrayStorage Implementation
219template <typename QuantizedElementType, typename AllocationPolicy>
221: ArrayNum(0)
222, ArrayMaxCapacity(AllocatorInstance.GetInitialCapacity())
223{
224}
225
226template <typename QuantizedElementType, typename AllocationPolicy>
228{
229 const SizeType NewCapacity = AllocatorInstance.CalculateNewCapacity(InNum);
230 AllocatorInstance.ResizeAllocation(Context, ArrayNum, NewCapacity);
231 ArrayMaxCapacity = NewCapacity;
232
233 if (NewCapacity > ArrayNum)
234 {
235 // To avoid issues with bad data in padding we always zero initialize new memory.
236 FMemory::Memzero(GetData() + ArrayNum, (NewCapacity - ArrayNum) * sizeof(ElementType));
237 }
238
239 ArrayNum = FMath::Min(InNum, NewCapacity);
240}
241
242template <typename QuantizedElementType, typename AllocationPolicy>
244{
245 AllocatorInstance.ResizeAllocation(Context, ArrayNum, 0);
246 ArrayMaxCapacity = AllocatorInstance.GetInitialCapacity();
247 ArrayNum = 0;
248}
249
250template <typename QuantizedElementType, typename AllocationPolicy>
252{
253 AllocatorInstance.Initialize();
254
255 const SizeType SourceNum = Source.Num();
256 const SizeType NewCapacity = AllocatorInstance.CalculateNewCapacity(SourceNum);
257
258 AllocatorInstance.ResizeAllocation(Context, 0, NewCapacity);
259 CopyAssignItems(GetData(), Source.GetData(), SourceNum);
260
262 {
263 // To avoid issues with bad data in padding we always zero initialize new memory.
265 }
266
267 ArrayMaxCapacity = NewCapacity;
268 ArrayNum = SourceNum;
269}
270
271// FNetSerializerAlignedStorage implementation
272
274{
275 return Data;
276}
277
279{
280 return Data;
281}
282
284{
285 return StorageNum;
286}
287
289{
290 return StorageAlignment;
291}
292
293namespace AllocationPolicies
294{
295
296// FElementAllocationPolicy implementation
297
298template<typename ElementType>
300{
301 if (NumElements == 0)
302 {
303 if (Data)
304 {
305 Free(Context, Data);
306 Data = nullptr;
307 }
308 }
309 else
310 {
311 constexpr SIZE_T ElementSize = sizeof(ElementType);
312 constexpr SIZE_T ElementAlignment = alignof(ElementType);
313
314 Data = (ElementType*)Realloc(Context, Data, NumElements*ElementSize, ElementAlignment);
315 }
316}
317
318// TInlinedElementAllocationPolicy implementation
319
320template<uint32 NumInlineElements, typename SecondaryAllocator>
321template<typename ElementType>
323{
324 // Check if the new allocation will fit in the inline data area.
325 if (NumElements <= NumInlineElements)
326 {
327 // If the old allocation wasn't in the inline data area, relocate it into the inline data area.
328 if (SecondaryData.GetAllocation())
329 {
330 RelocateConstructItems<ElementType>((void*)InlineData, (ElementType*)SecondaryData.GetAllocation(), FMath::Min(PreviousNumElements, NumInlineElements));
331
332 // Free the old indirect allocation.
333 SecondaryData.ResizeAllocation(Context, 0, 0);
334 }
335 }
336 else
337 {
338 if (!SecondaryData.GetAllocation())
339 {
340 // Allocate new indirect memory for the data.
341 SecondaryData.ResizeAllocation(Context, 0, NumElements);
342
343 // Move the data out of the inline data area into the new allocation.
344 RelocateConstructItems<ElementType>((void*)SecondaryData.GetAllocation(), GetInlineElements(), PreviousNumElements);
345 }
346 else
347 {
348 // Reallocate the indirect data for the new size.
349 SecondaryData.ResizeAllocation(Context, PreviousNumElements, NumElements);
350 }
351 }
352}
353
354template<uint32 NumInlineElements, typename SecondaryAllocator>
355template<typename ElementType>
357{
358 // If the elements use less space than the inline allocation, only use the inline allocation as slack.
359 return NumElements <= NumInlineElements ? NumInlineElements : SecondaryData.CalculateNewCapacity(NumElements);
360}
361
362}
363
364}
#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
FORCEINLINE void CopyAssignItems(ElementType *Dest, const ElementType *Source, SizeType Count)
Definition MemoryOps.h:137
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
auto GetData(const TStringConversion< Converter, DefaultConversionSize > &Conversion) -> decltype(Conversion.Get())
Definition StringConv.h:802
uint32 Size
Definition VulkanMemory.cpp:4034
uint8_t uint8
Definition binka_ue_file_header.h:8
uint32_t uint32
Definition binka_ue_file_header.h:6
bool HasAllocation() const
Definition NetSerializerArrayStorage.h:41
SizeType CalculateNewCapacity(SizeType NumElements) const
Definition NetSerializerArrayStorage.h:39
void ResizeAllocation(FNetSerializationContext &Context, SizeType PreviousNumElements, SizeType NumElements)
Definition NetSerializerArrayStorage.h:299
SizeType GetInitialCapacity() const
Definition NetSerializerArrayStorage.h:43
ForElementType()
Definition NetSerializerArrayStorage.h:29
~ForElementType()
Definition NetSerializerArrayStorage.h:31
void Initialize()
Definition NetSerializerArrayStorage.h:35
ElementType * GetAllocation() const
Definition NetSerializerArrayStorage.h:33
Definition NetSerializerArrayStorage.h:21
uint32 SizeType
Definition NetSerializerArrayStorage.h:23
bool HasAllocation() const
Definition NetSerializerArrayStorage.h:91
SizeType CalculateNewCapacity(SizeType NumElements) const
Definition NetSerializerArrayStorage.h:356
ElementType * GetAllocation() const
Definition NetSerializerArrayStorage.h:76
SizeType GetInitialCapacity() const
Definition NetSerializerArrayStorage.h:93
void ResizeAllocation(FNetSerializationContext &Context, SizeType PreviousNumElements, SizeType NumElements)
Definition NetSerializerArrayStorage.h:322
Definition NetSerializerArrayStorage.h:65
typename SecondaryAllocator::SizeType SizeType
Definition NetSerializerArrayStorage.h:67
Definition NetSerializationContext.h:31
Definition NetSerializerArrayStorage.h:178
const uint8 * GetData() const
Definition NetSerializerArrayStorage.h:273
SizeType GetAlignment() const
Definition NetSerializerArrayStorage.h:288
IRISCORE_API void Clone(FNetSerializationContext &Context, const FNetSerializerAlignedStorage &Source)
Definition NetSerializerArrayStorage.cpp:78
IRISCORE_API void AdjustSize(FNetSerializationContext &Context, SizeType InNum, SizeType InAlignment)
Definition NetSerializerArrayStorage.cpp:26
AllocationPolicies::FElementAllocationPolicy::SizeType SizeType
Definition NetSerializerArrayStorage.h:181
SizeType Num() const
Definition NetSerializerArrayStorage.h:283
Definition NetSerializerArrayStorage.h:120
void Clone(FNetSerializationContext &Context, const ArrayType &Source)
Definition NetSerializerArrayStorage.h:251
SizeType Num() const
Definition NetSerializerArrayStorage.h:162
FNetSerializerArrayStorage()
Definition NetSerializerArrayStorage.h:220
QuantizedElementType ElementType
Definition NetSerializerArrayStorage.h:127
const ElementType * GetData() const
Definition NetSerializerArrayStorage.h:160
FNetSerializerArrayStorage< QuantizedElementType, AllocationPolicy > ArrayType
Definition NetSerializerArrayStorage.h:126
ElementType * GetData()
Definition NetSerializerArrayStorage.h:161
void AdjustSize(FNetSerializationContext &Context, SizeType InNum)
Definition NetSerializerArrayStorage.h:227
AllocationPolicy::SizeType SizeType
Definition NetSerializerArrayStorage.h:130
void Free(FNetSerializationContext &Context)
Definition NetSerializerArrayStorage.h:243
AllocationPolicy::template ForElementType< ElementType > ElementAllocatorType
Definition NetSerializerArrayStorage.h:129
Definition NetworkVersion.cpp:28
static UE_FORCEINLINE_HINT void * Memzero(void *Dest, SIZE_T Count)
Definition UnrealMemory.h:131
Definition IsPODType.h:12
Definition IsTriviallyCopyAssignable.h:13
Definition TypeCompatibleBytes.h:24