UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
ContainerAllocationPolicies.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#include "CoreTypes.h"
7#include "HAL/PlatformMath.h"
8#include "HAL/UnrealMemory.h"
13#include "Templates/MemoryOps.h"
15#include <type_traits>
16
17
18// Array slack tracking is a debug feature to track unused space in heap allocated TArray (and TScriptArray) structures. This feature increases heap
19// memory usage, and costs perf, so it is usually disabled by default. Only works in builds where LLM is compiled in, but doesn't require -llm to be
20// active. Note that cooks will run quite slow with tracking enabled due to involving significantly more allocations than the engine, so be careful
21// about leaving this enabled when kicking off a cook (including !WITH_EDITOR ensures it will only be enabled for client builds). For more details,
22// see additional comments in LowLevelMemTracker.cpp.
23#ifndef UE_ENABLE_ARRAY_SLACK_TRACKING
24#define UE_ENABLE_ARRAY_SLACK_TRACKING (0 && !WITH_EDITOR)
25#endif
26
27
28#if UE_ENABLE_ARRAY_SLACK_TRACKING
29
33
34// For detailed tracking of array slack waste, we need to add a header to heap allocations. It's impossible to keep track of the TArray structure itself,
35// because it can be inside other structures, and potentially moved around in unsafe ways, while the heap allocation the TArray points to is invariant.
36// The heap allocations also have an advantage in that the contents are copied on Move or Realloc, simplifying tracking.
38{
39 FArraySlackTrackingHeader* Next; // Linked list of tracked items
41 uint16 AllocOffset; // Offset below the header to the start of the actual allocation, to account for alignment padding
42 uint8 Tag;
44 uint32 FirstAllocFrame; // Frame where array allocation first occurred
45 uint32 ReallocCount; // Number of times realloc happened
46 uint32 ArrayPeak; // Peak observed ArrayNum
48
49 // Note that we initially set the slack tracking ArrayNum to INDEX_NONE. The container allocator is used by both arrays and
50 // other containers (Set / Map / Hash), and we don't know it's actually an array until "UpdateNumUsed" is called on it.
51 int64 ArrayNum;
52 int64 ArrayMax;
53 uint64 StackFrames[9];
54
55 CORE_API void AddAllocation();
56 CORE_API void RemoveAllocation();
58 CORE_API FORCENOINLINE static void* Realloc(void* Ptr, int64 Count, uint64 ElemSize, int32 Alignment);
59
60 static void Free(void* Ptr)
61 {
62 if (Ptr)
63 {
65 TrackingHeader->RemoveAllocation();
66
67 Ptr = (uint8*)TrackingHeader - TrackingHeader->AllocOffset;
68
69 FMemory::Free(Ptr);
70 }
71 }
72
74 {
75 if (Ptr)
76 {
78
79 TrackingHeader->UpdateNumUsed(NewNumUsed);
80 }
81 }
82
83 static UE_FORCEINLINE_HINT void DisableTracking(void* Ptr)
84 {
85 if (Ptr)
86 {
88
89 TrackingHeader->RemoveAllocation();
90
91 // When disabling tracking, we need to also reset ArrayNum, as it's used internally as a flag specifying whether
92 // the allocation is currently tracked. We don't reset this inside RemoveAllocation, because ArrayNum needs to
93 // persist during realloc of tracked allocations, where RemoveAllocation is called, followed by AddAllocation.
94 TrackingHeader->ArrayNum = INDEX_NONE;
95 }
96 }
97
99 {
100 return (ArrayMax - ArrayNum) * ElemSize;
101 }
102};
103#endif // UE_ENABLE_ARRAY_SLACK_TRACKING
104
105// This option disables array slack for initial allocations, e.g where TArray::SetNum
106// is called. This tends to save a lot of memory with almost no measured performance cost.
107// NOTE: This can cause latent memory corruption issues to become more prominent
108#ifndef CONTAINER_INITIAL_ALLOC_ZERO_SLACK
109#define CONTAINER_INITIAL_ALLOC_ZERO_SLACK 1 // ON
110#endif
111
112#if defined(UE_CONTAINER_SLACK_GROWTH_FACTOR_NUMERATOR) && !defined(UE_CONTAINER_SLACK_GROWTH_FACTOR_DENOMINATOR)
113 #error If UE_CONTAINER_SLACK_GROWTH_FACTOR_NUMERATOR is defined you must also define UE_CONTAINER_SLACK_GROWTH_FACTOR_DENOMINATOR
114#endif
115
116#if defined(UE_CONTAINER_SLACK_GROWTH_FACTOR_DENOMINATOR) && !defined(UE_CONTAINER_SLACK_GROWTH_FACTOR_NUMERATOR)
117 #error If UE_CONTAINER_SLACK_GROWTH_FACTOR_DENOMINATOR is defined you must also define UE_CONTAINER_SLACK_GROWTH_FACTOR_NUMERATOR
118#endif
119
120#ifndef UE_CONTAINER_SLACK_GROWTH_FACTOR_NUMERATOR
121 #if AGGRESSIVE_MEMORY_SAVING
122 #define UE_CONTAINER_SLACK_GROWTH_FACTOR_NUMERATOR 1
123 #else
124 #define UE_CONTAINER_SLACK_GROWTH_FACTOR_NUMERATOR 3
125 #endif
126#endif
127
128#ifndef UE_CONTAINER_SLACK_GROWTH_FACTOR_DENOMINATOR
129 #if AGGRESSIVE_MEMORY_SAVING
130 #define UE_CONTAINER_SLACK_GROWTH_FACTOR_DENOMINATOR 4
131 #else
132 #define UE_CONTAINER_SLACK_GROWTH_FACTOR_DENOMINATOR 8
133 #endif
134#endif
135static_assert(UE_CONTAINER_SLACK_GROWTH_FACTOR_DENOMINATOR > 0, "UE_CONTAINER_SLACK_GROWTH_FACTOR_DENOMINATOR must be greater than 0");
136static_assert(UE_CONTAINER_SLACK_GROWTH_FACTOR_DENOMINATOR > UE_CONTAINER_SLACK_GROWTH_FACTOR_NUMERATOR, "UE_CONTAINER_SLACK_GROWTH_FACTOR_DENOMINATOR must be greater than UE_CONTAINER_SLACK_GROWTH_FACTOR_NUMERATOR");
137
138template <typename SizeType>
139UE_FORCEINLINE_HINT SizeType DefaultCalculateSlackShrink(SizeType NewMax, SizeType CurrentMax, SIZE_T BytesPerElement, bool bAllowQuantize, uint32 Alignment = DEFAULT_ALIGNMENT)
140{
141 SizeType Retval;
142 checkSlow(NewMax < CurrentMax);
143
144 // If the container has too much slack, shrink it to exactly fit the number of elements.
145 const SizeType CurrentSlackElements = CurrentMax - NewMax;
146 const SIZE_T CurrentSlackBytes = (CurrentMax - NewMax)*BytesPerElement;
147 const bool bTooManySlackBytes = CurrentSlackBytes >= 16384;
148 const bool bTooManySlackElements = 3 * NewMax < 2 * CurrentMax;
149 if ((bTooManySlackBytes || bTooManySlackElements) && (CurrentSlackElements > 64 || !NewMax)) // hard coded 64 :-(
150 {
151 Retval = NewMax;
152 if (Retval > 0)
153 {
154 if (bAllowQuantize)
155 {
156 Retval = (SizeType)(FMemory::QuantizeSize(Retval * BytesPerElement, Alignment) / BytesPerElement);
157 }
158 }
159 }
160 else
161 {
162 Retval = CurrentMax;
163 }
164
165 return Retval;
166}
167
168template <typename SizeType>
169UE_FORCEINLINE_HINT SizeType DefaultCalculateSlackGrow(SizeType NewMax, SizeType CurrentMax, SIZE_T BytesPerElement, bool bAllowQuantize, uint32 Alignment = DEFAULT_ALIGNMENT)
170{
171#if !defined(AGGRESSIVE_MEMORY_SAVING)
172 #error "AGGRESSIVE_MEMORY_SAVING must be defined"
173#endif
174#if AGGRESSIVE_MEMORY_SAVING
175 const SIZE_T FirstGrow = 1;
176 const SIZE_T ConstantGrow = 0;
177#else
178 const SIZE_T FirstGrow = 4;
179 const SIZE_T ConstantGrow = 16;
180#endif
181
182 SizeType Retval;
183 checkSlow(NewMax > CurrentMax && NewMax > 0);
184
185 SIZE_T Grow = FirstGrow; // this is the amount for the first alloc
186
187#if CONTAINER_INITIAL_ALLOC_ZERO_SLACK
188 if (CurrentMax)
189 {
190 // Allocate slack for the array proportional to its size.
192 }
193 else if (SIZE_T(NewMax) > Grow)
194 {
195 Grow = SIZE_T(NewMax);
196 }
197#else
198 if (CurrentMax || SIZE_T(NewMax) > Grow)
199 {
200 // Allocate slack for the array proportional to its size.
202 }
203#endif
204
205 if (bAllowQuantize)
206 {
207 Retval = (SizeType)(FMemory::QuantizeSize(Grow * BytesPerElement, Alignment) / BytesPerElement);
208 }
209 else
210 {
211 Retval = (SizeType)Grow;
212 }
213 // NumElements and MaxElements are stored in 32 bit signed integers so we must be careful not to overflow here.
214 if (NewMax > Retval)
215 {
217 }
218
219 return Retval;
220}
221
222template <typename SizeType>
224{
225 SizeType Retval = NewMax;
226 checkSlow(NewMax > 0);
227 if (bAllowQuantize)
228 {
229 Retval = (SizeType)(FMemory::QuantizeSize(SIZE_T(Retval) * SIZE_T(BytesPerElement), Alignment) / BytesPerElement);
230 // NumElements and MaxElements are stored in 32 bit signed integers so we must be careful not to overflow here.
231 if (NewMax > Retval)
232 {
234 }
235 }
236
237 return Retval;
238}
239
242{
243};
244
245template <typename AllocatorType>
247{
248 enum { IsZeroConstruct = false };
250 enum { SupportsElementAlignment = false };
251 enum { SupportsSlackTracking = false };
252};
253
254template <typename AllocatorType>
256{
257};
258
259template <typename FromAllocatorType, typename ToAllocatorType>
261{
262 enum { Value = false };
263};
264
267{
268public:
271
273 enum { NeedsElementType = true };
274
276 enum { RequireRangeCheck = true };
277
282 template<typename ElementType>
284 {
291 void MoveToEmpty(ForElementType& Other);
292
300 template <typename OtherAllocatorType>
301 void MoveToEmptyFromOtherAllocator(typename OtherAllocatorType::template ForElementType<ElementType>& Other);
302
304 ElementType* GetAllocation() const;
305
312 void ResizeAllocation(
313 SizeType CurrentNum,
315 SIZE_T NumBytesPerElement
316 );
317
327 void ResizeAllocation(
328 SizeType CurrentNum,
330 SIZE_T NumBytesPerElement,
332 );
333
339 SizeType CalculateSlackReserve(
341 SIZE_T NumBytesPerElement
342 ) const;
343
352 SizeType CalculateSlackReserve(
354 SIZE_T NumBytesPerElement,
356 ) const;
357
364 SizeType CalculateSlackShrink(
366 SizeType CurrentMax,
367 SIZE_T NumBytesPerElement
368 ) const;
369
379 SizeType CalculateSlackShrink(
381 SizeType CurrentMax,
382 SIZE_T NumBytesPerElement,
384 ) const;
385
392 SizeType CalculateSlackGrow(
394 SizeType CurrentMax,
395 SIZE_T NumBytesPerElement
396 ) const;
397
407 SizeType CalculateSlackGrow(
409 SizeType CurrentMax,
410 SIZE_T NumBytesPerElement,
412 ) const;
413
419 SIZE_T GetAllocatedSize(SizeType CurrentMax, SIZE_T NumBytesPerElement) const;
420
422 bool HasAllocation() const;
423
425 SizeType GetInitialCapacity() const;
426
428 void SlackTrackerLogNum(SizeType NewNumUsed);
429 };
430
436};
437
438namespace UE::Core::Private
439{
440 [[noreturn]] CORE_API void OnInvalidAlignedHeapAllocatorNum(int32 NewNum, SIZE_T NumBytesPerElement);
441 [[noreturn]] CORE_API void OnInvalidSizedHeapAllocatorNum(int32 IndexSize, int64 NewNum, SIZE_T NumBytesPerElement);
442}
443
445template<uint32 Alignment = DEFAULT_ALIGNMENT>
447{
448public:
450
451 enum { NeedsElementType = false };
452 enum { RequireRangeCheck = true };
453
455 {
456 public:
457
460 : Data(nullptr)
461 {}
462
469 {
470 checkSlow(this != &Other);
471
472 if (Data)
473 {
474#if UE_ENABLE_ARRAY_SLACK_TRACKING
475 FArraySlackTrackingHeader::Free(Data);
476#else
477 FMemory::Free(Data);
478#endif
479 }
480
481 Data = Other.Data;
482 Other.Data = nullptr;
483 }
484
487 {
488 if(Data)
489 {
490#if UE_ENABLE_ARRAY_SLACK_TRACKING
491 FArraySlackTrackingHeader::Free(Data);
492#else
493 FMemory::Free(Data);
494#endif
495 }
496 }
497
498 // FContainerAllocatorInterface
500 {
501 return Data;
502 }
504 SizeType CurrentNum,
506 SIZE_T NumBytesPerElement
507 )
508 {
509 // Avoid calling FMemory::Realloc( nullptr, 0 ) as ANSI C mandates returning a valid pointer which is not what we want.
510 if (Data || NewMax)
511 {
512 static_assert(sizeof(int32) <= sizeof(SIZE_T), "SIZE_T is expected to be larger than int32");
513
514 // Check for under/overflow
516 {
517 UE::Core::Private::OnInvalidAlignedHeapAllocatorNum(NewMax, NumBytesPerElement);
518 }
519
520#if UE_ENABLE_ARRAY_SLACK_TRACKING
521 Data = (FScriptContainerElement*)FArraySlackTrackingHeader::Realloc(Data, NewMax, NumBytesPerElement, Alignment > alignof(FArraySlackTrackingHeader) ? Alignment : alignof(FArraySlackTrackingHeader));
522#else
523 Data = (FScriptContainerElement*)FMemory::Realloc( Data, NewMax*NumBytesPerElement, Alignment );
524#endif
525 }
526 }
528 {
529 return DefaultCalculateSlackReserve(NewMax, NumBytesPerElement, true, Alignment);
530 }
532 {
533 return DefaultCalculateSlackShrink(NewMax, CurrentMax, NumBytesPerElement, true, Alignment);
534 }
536 {
537 return DefaultCalculateSlackGrow(NewMax, CurrentMax, NumBytesPerElement, true, Alignment);
538 }
539
540 SIZE_T GetAllocatedSize(SizeType CurrentMax, SIZE_T NumBytesPerElement) const
541 {
542 return CurrentMax * NumBytesPerElement;
543 }
544
545 bool HasAllocation() const
546 {
547 return !!Data;
548 }
549
551 {
552 return 0;
553 }
554
555#if UE_ENABLE_ARRAY_SLACK_TRACKING
556 UE_FORCEINLINE_HINT void SlackTrackerLogNum(SizeType NewNumUsed)
557 {
558 FArraySlackTrackingHeader::UpdateNumUsed(Data, (int64)NewNumUsed);
559 }
560
561 // Suppress slack tracking on an allocation -- should be called whenever the container may have been resized.
562 // Useful for debug allocations you don't want to show up in slack reports.
564 {
565 FArraySlackTrackingHeader::DisableTracking(Data);
566 }
567#endif
568
569 private:
571 ForAnyElementType& operator=(const ForAnyElementType&);
572
575 };
576
577 template<typename ElementType>
579 {
580 static constexpr SIZE_T MinimumAlignment = (Alignment <= __STDCPP_DEFAULT_NEW_ALIGNMENT__) ? __STDCPP_DEFAULT_NEW_ALIGNMENT__ : Alignment;
581
582 public:
585 {
586 static_assert(alignof(ElementType) <= MinimumAlignment, "Using TAlignedHeapAllocator with an alignment lower than the element type's alignment - please update the alignment parameter");
587 }
588
590 {
591 return (ElementType*)ForAnyElementType::GetAllocation();
592 }
593 };
594};
595
596template <uint32 Alignment>
597struct TAllocatorTraits<TAlignedHeapAllocator<Alignment>> : TAllocatorTraitsBase<TAlignedHeapAllocator<Alignment>>
598{
599 enum { IsZeroConstruct = true };
600 enum { SupportsSlackTracking = true };
601};
602
603template <int IndexSize>
605{
606 // Fabricate a compile-time false result that's still dependent on the template parameter
607 static_assert(IndexSize == IndexSize+1, "Unsupported allocator index size.");
608};
609
610template <> struct TBitsToSizeType<8> { using Type = int8; };
611template <> struct TBitsToSizeType<16> { using Type = int16; };
612template <> struct TBitsToSizeType<32> { using Type = int32; };
613template <> struct TBitsToSizeType<64> { using Type = int64; };
614
616template <int IndexSize, typename BaseMallocType = FMemory>
618{
619public:
622
623private:
624 using USizeType = std::make_unsigned_t<SizeType>;
625
626public:
627 enum { NeedsElementType = false };
628 enum { RequireRangeCheck = true };
629
631 {
632 template <int, typename>
634
635 public:
638 : Data(nullptr)
639 {}
640
642 explicit consteval ForAnyElementType(EConstEval)
643 : Data(nullptr)
644 {}
645
652 template <typename OtherAllocator>
653 UE_FORCEINLINE_HINT void MoveToEmptyFromOtherAllocator(typename OtherAllocator::ForAnyElementType& Other)
654 {
655 checkSlow((void*)this != (void*)&Other);
656
657 if (Data)
658 {
659#if UE_ENABLE_ARRAY_SLACK_TRACKING
660 FArraySlackTrackingHeader::Free(Data);
661#else
662 BaseMallocType::Free(Data);
663#endif
664 }
665
666 Data = Other.Data;
667 Other.Data = nullptr;
668 }
669
681
684 {
685 if(Data)
686 {
687#if UE_ENABLE_ARRAY_SLACK_TRACKING
688 FArraySlackTrackingHeader::Free(Data);
689#else
690 BaseMallocType::Free(Data);
691#endif
692 }
693 }
694
695 // FContainerAllocatorInterface
697 {
698 return Data;
699 }
700 void ResizeAllocation(SizeType CurrentNum, SizeType NewMax, SIZE_T NumBytesPerElement)
701 {
702 // Avoid calling FMemory::Realloc( nullptr, 0 ) as ANSI C mandates returning a valid pointer which is not what we want.
703 if (Data || NewMax)
704 {
705 static_assert(sizeof(SizeType) <= sizeof(SIZE_T), "SIZE_T is expected to handle all possible sizes");
706
707 // Check for under/overflow
709 if constexpr (sizeof(SizeType) == sizeof(SIZE_T))
710 {
711 bInvalidResize = bInvalidResize || (SIZE_T)(USizeType)NewMax > (SIZE_T)TNumericLimits<SizeType>::Max() / NumBytesPerElement;
712 }
714 {
715 UE::Core::Private::OnInvalidSizedHeapAllocatorNum(IndexSize, NewMax, NumBytesPerElement);
716 }
717
718#if UE_ENABLE_ARRAY_SLACK_TRACKING
719 Data = (FScriptContainerElement*)FArraySlackTrackingHeader::Realloc(Data, NewMax, NumBytesPerElement, 0);
720#else
721 Data = (FScriptContainerElement*)BaseMallocType::Realloc( Data, NewMax*NumBytesPerElement );
722#endif
723 }
724 }
726 {
727 // Avoid calling FMemory::Realloc( nullptr, 0 ) as ANSI C mandates returning a valid pointer which is not what we want.
728 if (Data || NewMax)
729 {
730 static_assert(sizeof(SizeType) <= sizeof(SIZE_T), "SIZE_T is expected to handle all possible sizes");
731
732 // Check for under/overflow
734 if constexpr (sizeof(SizeType) == sizeof(SIZE_T))
735 {
736 bInvalidResize = bInvalidResize || ((SIZE_T)(USizeType)NewMax > (SIZE_T)TNumericLimits<SizeType>::Max() / NumBytesPerElement);
737 }
739 {
740 UE::Core::Private::OnInvalidSizedHeapAllocatorNum(IndexSize, NewMax, NumBytesPerElement);
741 }
742
743#if UE_ENABLE_ARRAY_SLACK_TRACKING
744 Data = (FScriptContainerElement*)FArraySlackTrackingHeader::Realloc(Data, NewMax, NumBytesPerElement, AlignmentOfElement > alignof(FArraySlackTrackingHeader) ? AlignmentOfElement : alignof(FArraySlackTrackingHeader));
745#else
746 Data = (FScriptContainerElement*)BaseMallocType::Realloc( Data, NewMax*NumBytesPerElement, AlignmentOfElement );
747#endif
748 }
749 }
751 {
752 return DefaultCalculateSlackReserve(NewMax, NumBytesPerElement, true);
753 }
759 {
760 return DefaultCalculateSlackShrink(NewMax, CurrentMax, NumBytesPerElement, true);
761 }
763 {
764 return DefaultCalculateSlackShrink(NewMax, CurrentMax, NumBytesPerElement, true, (uint32)AlignmentOfElement);
765 }
767 {
768 return DefaultCalculateSlackGrow(NewMax, CurrentMax, NumBytesPerElement, true);
769 }
771 {
772 return DefaultCalculateSlackGrow(NewMax, CurrentMax, NumBytesPerElement, true, (uint32)AlignmentOfElement);
773 }
774
775 SIZE_T GetAllocatedSize(SizeType CurrentMax, SIZE_T NumBytesPerElement) const
776 {
777 return CurrentMax * NumBytesPerElement;
778 }
779
780 bool HasAllocation() const
781 {
782 return !!Data;
783 }
784
785 constexpr SizeType GetInitialCapacity() const
786 {
787 return 0;
788 }
789
790#if UE_ENABLE_ARRAY_SLACK_TRACKING
791 UE_FORCEINLINE_HINT void SlackTrackerLogNum(SizeType NewNumUsed)
792 {
793 FArraySlackTrackingHeader::UpdateNumUsed(Data, (int64)NewNumUsed);
794 }
795
796 // Suppress slack tracking on an allocation -- should be called whenever the container may have been resized.
797 // Useful for debug allocations you don't want to show up in slack reports.
799 {
800 FArraySlackTrackingHeader::DisableTracking(Data);
801 }
802#endif
803
804 private:
806 ForAnyElementType& operator=(const ForAnyElementType&);
807
810 };
811
812 template<typename ElementType>
814 {
815 public:
817 ForElementType() = default;
818 explicit consteval ForElementType(EConstEval)
820 {
821 }
822
824 {
825 return (ElementType*)ForAnyElementType::GetAllocation();
826 }
827 };
828};
829
830template <int IndexSize> class TSizedDefaultAllocator : public TSizedHeapAllocator<IndexSize> { public: typedef TSizedHeapAllocator<IndexSize> Typedef; };
832
834template <int IndexSize> class TSizedNonshrinkingAllocator : public TSizedHeapAllocator<IndexSize>
835{
836public:
838 enum { ShrinkByDefault = false };
839};
840
841// Define the ResizeAllocation functions with the regular allocator as exported to avoid bloat
842#if !UE_MERGED_MODULES && !defined(UE_HEADER_UNITS)
843extern template CORE_API FORCENOINLINE void TSizedHeapAllocator<32, FMemory>::ForAnyElementType::ResizeAllocation(SizeType CurrentNum, SizeType NewMax, SIZE_T NumBytesPerElement);
844extern template CORE_API FORCENOINLINE void TSizedHeapAllocator<32, FMemory>::ForAnyElementType::ResizeAllocation(SizeType CurrentNum, SizeType NewMax, SIZE_T NumBytesPerElement, uint32 AlignmentOfElement);
845extern template CORE_API FORCENOINLINE void TSizedHeapAllocator<64, FMemory>::ForAnyElementType::ResizeAllocation(SizeType CurrentNum, SizeType NewMax, SIZE_T NumBytesPerElement);
846extern template CORE_API FORCENOINLINE void TSizedHeapAllocator<64, FMemory>::ForAnyElementType::ResizeAllocation(SizeType CurrentNum, SizeType NewMax, SIZE_T NumBytesPerElement, uint32 AlignmentOfElement);
847#endif
848
849template <uint8 IndexSize>
851{
852 enum { IsZeroConstruct = true };
853 enum { SupportsElementAlignment = true };
854 enum { SupportsSlackTracking = true };
855};
856
858
859template <uint8 FromIndexSize, uint8 ToIndexSize>
861{
862 // Allow conversions between different int width versions of the allocator
863 enum { Value = true };
864};
865
871namespace UE::Core::Private
872{
873 // This concept allows us to support allocators which don't specify `enum { ShrinkByDefault = ...; }`.
874 template <typename AllocatorType>
875 concept CHasShrinkByDefault = requires { AllocatorType::ShrinkByDefault; };
876
877 // Returns the value of AllocatorType::ShrinkByDefault if the enum exists, or bFallback if the enum is absent.
878 template <bool bFallback, typename AllocatorType>
879 consteval bool ShrinkByDefaultOr()
880 {
882 {
883 return AllocatorType::ShrinkByDefault;
884 }
885 else
886 {
887 return bFallback;
888 }
889 }
890}
891
892template <uint32 NumInlineElements, int IndexSize, typename SecondaryAllocator = FDefaultAllocator>
894{
895public:
897
898 static_assert(std::is_same_v<SizeType, typename SecondaryAllocator::SizeType>, "Secondary allocator SizeType mismatch");
899
900 enum { NeedsElementType = true };
901 enum { RequireRangeCheck = true };
902 enum { ShrinkByDefault = UE::Core::Private::ShrinkByDefaultOr<true, SecondaryAllocator>() };
903
904 template<typename ElementType>
906 {
907 public:
908
910 constexpr ForElementType()
911 {
913 {
914 for (uint8& Byte : InlineData)
915 {
916 Byte = 0;
917 }
918 }
919 }
920
921 explicit consteval ForElementType(EConstEval)
922 : InlineData() // Force value initialization
923 , SecondaryData(ConstEval)
924 {
925 }
926
933 {
934 checkSlow(this != &Other);
935
936 if (!Other.SecondaryData.GetAllocation())
937 {
938 // Relocate objects from other inline storage only if it was stored inline in Other
939 RelocateConstructItems<ElementType>((void*)InlineData, Other.GetInlineElements(), NumInlineElements);
940 }
941
942 // Move secondary storage in any case.
943 // This will move secondary storage if it exists but will also handle the case where secondary storage is used in Other but not in *this.
944 SecondaryData.MoveToEmpty(Other.SecondaryData);
945 }
946
947 // FContainerAllocatorInterface
949 {
950 if (ElementType* Result = SecondaryData.GetAllocation())
951 {
952 return Result;
953 }
954 return GetInlineElements();
955 }
956
957 void ResizeAllocation(SizeType CurrentNum, SizeType NewMax,SIZE_T NumBytesPerElement)
958 {
959 // Make sure the number of live elements is still withing the allocation since we only memmove, not destruct
960 checkSlow(CurrentNum <= NewMax);
961
962 // Check if the new allocation will fit in the inline data area.
963 if(NewMax <= NumInlineElements)
964 {
965 // If the old allocation wasn't in the inline data area, relocate it into the inline data area.
966 if(SecondaryData.GetAllocation())
967 {
968 RelocateConstructItems<ElementType>((void*)InlineData, (ElementType*)SecondaryData.GetAllocation(), CurrentNum);
969
970 // Free the old indirect allocation.
971 SecondaryData.ResizeAllocation(0,0,NumBytesPerElement);
972 }
973 }
974 else
975 {
976 if(!SecondaryData.GetAllocation())
977 {
978 // Allocate new indirect memory for the data.
979 SecondaryData.ResizeAllocation(0,NewMax,NumBytesPerElement);
980
981 // Move the data out of the inline data area into the new allocation.
982 RelocateConstructItems<ElementType>((void*)SecondaryData.GetAllocation(), GetInlineElements(), CurrentNum);
983 }
984 else
985 {
986 // Reallocate the indirect data for the new size.
987 SecondaryData.ResizeAllocation(CurrentNum, NewMax, NumBytesPerElement);
988 }
989 }
990 }
991
993 {
994 // If the elements use less space than the inline allocation, only use the inline allocation as slack.
995 return NewMax <= NumInlineElements ?
996 NumInlineElements :
997 SecondaryData.CalculateSlackReserve(NewMax, NumBytesPerElement);
998 }
1000 {
1001 // If the elements use less space than the inline allocation, only use the inline allocation as slack.
1002 return NewMax <= NumInlineElements ?
1003 NumInlineElements :
1004 SecondaryData.CalculateSlackShrink(NewMax, CurrentMax, NumBytesPerElement);
1005 }
1007 {
1008 // If the elements use less space than the inline allocation, only use the inline allocation as slack.
1009 // Also, when computing slack growth, don't count inline elements -- the slack algorithm has a special
1010 // case to save memory on the initial heap allocation, versus subsequent reallocations, and we don't
1011 // want the inline elements to be treated as if they were the first heap allocation.
1012 return NewMax <= NumInlineElements ?
1013 NumInlineElements :
1014 SecondaryData.CalculateSlackGrow(NewMax, CurrentMax <= NumInlineElements ? 0 : CurrentMax, NumBytesPerElement);
1015 }
1016
1017 SIZE_T GetAllocatedSize(SizeType CurrentMax, SIZE_T NumBytesPerElement) const
1018 {
1019 if (CurrentMax > NumInlineElements)
1020 {
1021 return SecondaryData.GetAllocatedSize(CurrentMax, NumBytesPerElement);
1022 }
1023 return 0;
1024 }
1025
1026 bool HasAllocation() const
1027 {
1028 return SecondaryData.HasAllocation();
1029 }
1030
1032 {
1033 return NumInlineElements;
1034 }
1035
1036#if UE_ENABLE_ARRAY_SLACK_TRACKING
1037 UE_FORCEINLINE_HINT void SlackTrackerLogNum(SizeType NewNumUsed)
1038 {
1040 {
1041 SecondaryData.SlackTrackerLogNum(NewNumUsed);
1042 }
1043 }
1044#endif
1045
1046 private:
1048 ForElementType& operator=(const ForElementType&);
1049
1051 alignas(ElementType) uint8 InlineData[sizeof(ElementType) * NumInlineElements];
1052
1054 typename SecondaryAllocator::template ForElementType<ElementType> SecondaryData;
1055
1057 ElementType* GetInlineElements() const
1058 {
1059 return (ElementType*)InlineData;
1060 }
1061 };
1062
1063 typedef void ForAnyElementType;
1064};
1065
1066template <uint32 NumInlineElements, int IndexSize, typename SecondaryAllocator>
1067struct TAllocatorTraits<TSizedInlineAllocator<NumInlineElements, IndexSize, SecondaryAllocator>> : TAllocatorTraitsBase<TSizedInlineAllocator<NumInlineElements, IndexSize, SecondaryAllocator>>
1068{
1069 enum { SupportsSlackTracking = true };
1070};
1071
1072template <uint32 NumInlineElements, typename SecondaryAllocator = FDefaultAllocator>
1074
1075template <uint32 NumInlineElements, typename SecondaryAllocator = FDefaultAllocator64>
1077
1085template <uint32 NumInlineElements>
1087{
1088public:
1090
1091 enum { NeedsElementType = true };
1092 enum { RequireRangeCheck = true };
1093
1094 template<typename ElementType>
1096 {
1097 public:
1100 : Data(GetInlineElements())
1101 {
1102 static_assert(alignof(ElementType) <= __STDCPP_DEFAULT_NEW_ALIGNMENT__, "TNonRelocatableInlineAllocator uses GMalloc's default alignment, which is lower than the element type's alignment - please consider a different approach");
1103 }
1104
1106 {
1107 if (HasAllocation())
1108 {
1109#if UE_ENABLE_ARRAY_SLACK_TRACKING
1110 FArraySlackTrackingHeader::Free(Data);
1111#else
1112 FMemory::Free(Data);
1113#endif
1114 }
1115 }
1116
1123 {
1124 checkSlow(this != &Other);
1125
1126 if (HasAllocation())
1127 {
1128#if UE_ENABLE_ARRAY_SLACK_TRACKING
1129 FArraySlackTrackingHeader::Free(Data);
1130#else
1131 FMemory::Free(Data);
1132#endif
1133 }
1134
1135 if (Other.HasAllocation())
1136 {
1137 Data = Other.Data;
1138 Other.Data = Other.GetInlineElements();
1139 }
1140 else
1141 {
1142 Data = GetInlineElements();
1143 RelocateConstructItems<ElementType>(GetInlineElements(), Other.GetInlineElements(), NumInlineElements);
1144 }
1145 }
1146
1147 // FContainerAllocatorInterface
1149 {
1150 return Data;
1151 }
1152
1153 void ResizeAllocation(SizeType CurrentNum, SizeType NewMax,SIZE_T NumBytesPerElement)
1154 {
1155 // Make sure the number of live elements is still withing the allocation since we only memmove, not destruct
1156 checkSlow(CurrentNum <= NewMax);
1157
1158 // Check if the new allocation will fit in the inline data area.
1159 if(NewMax <= NumInlineElements)
1160 {
1161 // If the old allocation wasn't in the inline data area, relocate it into the inline data area.
1162 if(HasAllocation())
1163 {
1164 RelocateConstructItems<ElementType>(GetInlineElements(), Data, CurrentNum);
1165#if UE_ENABLE_ARRAY_SLACK_TRACKING
1166 FArraySlackTrackingHeader::Free(Data);
1167#else
1168 FMemory::Free(Data);
1169#endif
1170 Data = GetInlineElements();
1171 }
1172 }
1173 else
1174 {
1175 if (HasAllocation())
1176 {
1177 // Reallocate the indirect data for the new size.
1178#if UE_ENABLE_ARRAY_SLACK_TRACKING
1179 Data = (ElementType*)FArraySlackTrackingHeader::Realloc(Data, (int32)NewMax, (int32)NumBytesPerElement, 0);
1180#else
1181 Data = (ElementType*)FMemory::Realloc(Data, NewMax*NumBytesPerElement);
1182#endif
1183 }
1184 else
1185 {
1186 // Allocate new indirect memory for the data.
1187#if UE_ENABLE_ARRAY_SLACK_TRACKING
1188 Data = (ElementType*)FArraySlackTrackingHeader::Realloc(nullptr, (int32)NewMax, (int32)NumBytesPerElement, 0);
1189#else
1190 Data = (ElementType*)FMemory::Realloc(nullptr, NewMax*NumBytesPerElement);
1191#endif
1192
1193 // Move the data out of the inline data area into the new allocation.
1194 RelocateConstructItems<ElementType>(Data, GetInlineElements(), CurrentNum);
1195 }
1196 }
1197 }
1198
1200 {
1201 // If the elements use less space than the inline allocation, only use the inline allocation as slack.
1202 return (NewMax <= NumInlineElements) ? NumInlineElements : DefaultCalculateSlackReserve(NewMax, NumBytesPerElement, true);
1203 }
1204
1206 {
1207 // If the elements use less space than the inline allocation, only use the inline allocation as slack.
1208 return (NewMax <= NumInlineElements) ? NumInlineElements : DefaultCalculateSlackShrink(NewMax, CurrentMax, NumBytesPerElement, true);
1209 }
1210
1212 {
1213 // If the elements use less space than the inline allocation, only use the inline allocation as slack.
1214 return (NewMax <= NumInlineElements) ? NumInlineElements : DefaultCalculateSlackGrow(NewMax, CurrentMax, NumBytesPerElement, true);
1215 }
1216
1217 SIZE_T GetAllocatedSize(SizeType CurrentMax, SIZE_T NumBytesPerElement) const
1218 {
1219 return HasAllocation() ? (CurrentMax * NumBytesPerElement) : 0;
1220 }
1221
1223 {
1224 return Data != GetInlineElements();
1225 }
1226
1228 {
1229 return NumInlineElements;
1230 }
1231
1232#if UE_ENABLE_ARRAY_SLACK_TRACKING
1233 UE_FORCEINLINE_HINT void SlackTrackerLogNum(SizeType NewNumUsed)
1234 {
1235 if (HasAllocation())
1236 {
1238
1239 TrackingHeader->UpdateNumUsed((int64)NewNumUsed);
1240 }
1241 }
1242#endif
1243
1244 private:
1245 ForElementType(const ForElementType&) = delete;
1246 ForElementType& operator=(const ForElementType&) = delete;
1247
1249 ElementType* Data;
1250
1252 TTypeCompatibleBytes<ElementType> InlineData[NumInlineElements];
1253
1255 UE_FORCEINLINE_HINT ElementType* GetInlineElements() const
1256 {
1257 return (ElementType*)InlineData;
1258 }
1259 };
1260
1261 typedef void ForAnyElementType;
1262};
1263
1264template <uint32 NumInlineElements>
1265struct TAllocatorTraits<TNonRelocatableInlineAllocator<NumInlineElements>> : TAllocatorTraitsBase<TNonRelocatableInlineAllocator<NumInlineElements>>
1266{
1267 enum { SupportsSlackTracking = true };
1268};
1269
1274template <uint32 NumInlineElements>
1276{
1277public:
1279
1280 enum { NeedsElementType = true };
1281 enum { RequireRangeCheck = true };
1282 enum { ShrinkByDefault = false };
1283
1284 template<typename ElementType>
1286 {
1287 public:
1288
1291 {
1292 }
1293
1300 {
1301 checkSlow(this != &Other);
1302
1303 // Relocate objects from other inline storage
1304 RelocateConstructItems<ElementType>((void*)InlineData, Other.GetInlineElements(), NumInlineElements);
1305 }
1306
1307 // FContainerAllocatorInterface
1309 {
1310 return GetInlineElements();
1311 }
1312
1313 void ResizeAllocation(SizeType CurrentNum, SizeType NewMax,SIZE_T NumBytesPerElement)
1314 {
1315 // Ensure the requested allocation will fit in the inline data area.
1316 check(NewMax >= 0 && NewMax <= NumInlineElements);
1317 }
1318
1320 {
1321 // Ensure the requested allocation will fit in the inline data area.
1322 check(NewMax <= NumInlineElements);
1323 return NumInlineElements;
1324 }
1326 {
1327 // Ensure the requested allocation will fit in the inline data area.
1328 check(CurrentMax <= NumInlineElements);
1329 return NumInlineElements;
1330 }
1332 {
1333 // Ensure the requested allocation will fit in the inline data area.
1334 check(NewMax <= NumInlineElements);
1335 return NumInlineElements;
1336 }
1337
1338 SIZE_T GetAllocatedSize(SizeType CurrentMax, SIZE_T NumBytesPerElement) const
1339 {
1340 return 0;
1341 }
1342
1343 bool HasAllocation() const
1344 {
1345 return false;
1346 }
1347
1349 {
1350 return NumInlineElements;
1351 }
1352
1353 private:
1355 ForElementType& operator=(const ForElementType&);
1356
1358 TTypeCompatibleBytes<ElementType> InlineData[NumInlineElements];
1359
1361 ElementType* GetInlineElements() const
1362 {
1363 return (ElementType*)InlineData;
1364 }
1365 };
1366
1367 typedef void ForAnyElementType;
1368};
1369
1370// We want these to be correctly typed as int32, but we don't want them to have linkage, so we make them macros
1371#define NumBitsPerDWORD ((int32)32)
1372#define NumBitsPerDWORDLogTwo ((int32)5)
1373
1375
1376//
1377// Sparse array allocation definitions
1378//
1379
1381template<typename InElementAllocator = FDefaultAllocator,typename InBitArrayAllocator = FDefaultBitArrayAllocator>
1389
1390template <uint32 Alignment = DEFAULT_ALIGNMENT, typename InElementAllocator = TAlignedHeapAllocator<Alignment>,typename InBitArrayAllocator = FDefaultBitArrayAllocator>
1397
1399template<
1400 uint32 NumInlineElements,
1402 >
1415
1417template <uint32 NumInlineElements>
1419{
1420private:
1421
1423 enum { InlineBitArrayDWORDs = (NumInlineElements + NumBitsPerDWORD - 1) / NumBitsPerDWORD};
1424
1425public:
1426
1429};
1430
1431//
1432// Compact set allocation definitions - It operates entirely with uint8 because it includes its lookup table inline with the overall allocation
1433//
1434
1436{
1437 template <uint32 NumInlineElements, int32 ElementSize>
1438 constexpr int32 CalculateRequiredBytes()
1439 {
1440 constexpr uint32 TypeSize = 1 + (NumInlineElements > 0xff) + (NumInlineElements > 0xffff) * 2;
1441 constexpr uint32 HashSize = NumInlineElements < 8 ? 4 : FGenericPlatformMath::RoundUpToPowerOfTwo((NumInlineElements / 2) + 1);
1442 return Align(NumInlineElements*ElementSize, 4) + 4 + (NumInlineElements + HashSize) * TypeSize;
1443 }
1444}
1445
1447template<typename InElementAllocator = FDefaultAllocator>
1449{
1451 template <typename ElementType>
1453 {
1454 static constexpr size_t Value = alignof(typename InElementAllocator::template ForElementType<uint8>);
1455 };
1456
1457 template<int32 ElementSize>
1459};
1460
1461template<typename InElementAllocator>
1469
1471template<uint32 NumInlineElements, typename SecondaryAllocator = TCompactSetAllocator<>>
1473{
1474 template<int32 ElementSize>
1476
1478 template <typename ElementType>
1480 {
1481 static constexpr size_t ElementAlignof = alignof(ElementType);
1482 static constexpr size_t AllocatorAlignof = alignof(typename ElementAllocator<sizeof(ElementType)>::template ForElementType<uint8>);
1484 };
1485};
1486
1488template <uint32 NumInlineElements>
1490{
1491 template<int32 ElementSize>
1493
1495 template <typename ElementType>
1497 {
1498 static constexpr size_t ElementAlignof = alignof(ElementType);
1499 static constexpr size_t AllocatorAlignof = alignof(typename ElementAllocator<sizeof(ElementType)>::template ForElementType<uint8>);
1501 };
1502};
1503
1504
1505
1506//
1507// Set allocation definitions.
1508//
1509
1510#if !defined(DEFAULT_NUMBER_OF_ELEMENTS_PER_HASH_BUCKET)
1511# define DEFAULT_NUMBER_OF_ELEMENTS_PER_HASH_BUCKET 2
1512#endif
1513#define DEFAULT_BASE_NUMBER_OF_HASH_BUCKETS 8
1514#define DEFAULT_MIN_NUMBER_OF_HASHED_ELEMENTS 4
1515
1517template<
1523 >
1542
1543template<
1544 typename InSparseArrayAllocator,
1545 typename InHashAllocator,
1549>
1551 TAllocatorTraitsBase<TSparseSetAllocator<InSparseArrayAllocator, InHashAllocator, AverageNumberOfElementsPerHashBucket, BaseNumberOfHashBuckets, MinNumberOfHashedElements>>
1552{
1553 enum
1554 {
1556 };
1557};
1558
1560template<
1561 uint32 NumInlineElements,
1565 >
1567{
1568private:
1569
1570 enum { NumInlineHashBuckets = (NumInlineElements + AverageNumberOfElementsPerHashBucket - 1) / AverageNumberOfElementsPerHashBucket };
1571
1572 static_assert(NumInlineHashBuckets > 0 && !(NumInlineHashBuckets & (NumInlineHashBuckets - 1)), "Number of inline buckets must be a power of two");
1573
1574public:
1575
1578 {
1579 const uint32 NumDesiredHashBuckets = FPlatformMath::RoundUpToPowerOfTwo(NumHashedElements / AverageNumberOfElementsPerHashBucket);
1580 if (NumDesiredHashBuckets < NumInlineHashBuckets)
1581 {
1582 return NumInlineHashBuckets;
1583 }
1584
1586 {
1587 return NumInlineHashBuckets;
1588 }
1589
1590 return NumDesiredHashBuckets;
1591 }
1592
1595};
1596
1598template<
1599 uint32 NumInlineElements,
1602 >
1604{
1605private:
1606
1607 enum { NumInlineHashBuckets = (NumInlineElements + AverageNumberOfElementsPerHashBucket - 1) / AverageNumberOfElementsPerHashBucket };
1608
1609 static_assert(NumInlineHashBuckets > 0 && !(NumInlineHashBuckets & (NumInlineHashBuckets - 1)), "Number of inline buckets must be a power of two");
1610
1611public:
1612
1615 {
1616 const uint32 NumDesiredHashBuckets = FPlatformMath::RoundUpToPowerOfTwo(NumHashedElements / AverageNumberOfElementsPerHashBucket);
1617 if (NumDesiredHashBuckets < NumInlineHashBuckets)
1618 {
1619 return NumInlineHashBuckets;
1620 }
1621
1623 {
1624 return NumInlineHashBuckets;
1625 }
1626
1627 return NumDesiredHashBuckets;
1628 }
1629
1632};
1633
1634
1646
1647#ifndef UE_USE_COMPACT_SET_AS_DEFAULT
1648#define UE_USE_COMPACT_SET_AS_DEFAULT 0
1649#endif
1650
1651#if UE_USE_COMPACT_SET_AS_DEFAULT
1652class FDefaultSetAllocator : public TCompactSetAllocator<> { public: typedef TCompactSetAllocator<> Typedef; };
1653template<typename InSparseArrayAllocator = TSparseArrayAllocator<>, typename InHashAllocator = TInlineAllocator<1,FDefaultAllocator>, uint32... N>
1654class TSetAllocator : public TCompactSetAllocator<InHashAllocator> { public: typedef TCompactSetAllocator<InHashAllocator> Typedef; };
1655template <uint32 N, typename S = TCompactSetAllocator<>, uint32... NN>
1657template <uint32 N, uint32... Y>
1659#else
1661template<typename InSparseArrayAllocator = TSparseArrayAllocator<>, typename InHashAllocator = TInlineAllocator<1,FDefaultAllocator>, uint32... N>
1662class TSetAllocator : public TSparseSetAllocator<InSparseArrayAllocator, InHashAllocator, N...> { public: typedef TSparseSetAllocator<InSparseArrayAllocator, InHashAllocator, N...> Typedef; };
1663template<uint32 N, typename S = TSparseSetAllocator<TSparseArrayAllocator<FDefaultAllocator,FDefaultAllocator>,FDefaultAllocator>, uint32... NN>
1664class TInlineSetAllocator : public TInlineSparseSetAllocator<N, S, NN...> { public: typedef TInlineSparseSetAllocator<N, S, NN...> Typedef; };
1665template <uint32... N>
1666class TFixedSetAllocator : public TFixedSparseSetAllocator<N...> { public: typedef TFixedSparseSetAllocator<N...> Typedef; };
1667#endif
1668
1669template <int IndexSize> struct TAllocatorTraits<TSizedDefaultAllocator<IndexSize>> : TAllocatorTraits<typename TSizedDefaultAllocator<IndexSize>::Typedef> {};
1670
1671template <> struct TAllocatorTraits<FDefaultAllocator> : TAllocatorTraits<typename FDefaultAllocator ::Typedef> {};
1672template <> struct TAllocatorTraits<FDefaultSetAllocator> : TAllocatorTraits<typename FDefaultSetAllocator ::Typedef> {};
1673template <> struct TAllocatorTraits<FDefaultSparseSetAllocator> : TAllocatorTraits<typename FDefaultSparseSetAllocator ::Typedef> {};
1674template <> struct TAllocatorTraits<FDefaultBitArrayAllocator> : TAllocatorTraits<typename FDefaultBitArrayAllocator ::Typedef> {};
1675template <> struct TAllocatorTraits<FDefaultSparseArrayAllocator> : TAllocatorTraits<typename FDefaultSparseArrayAllocator::Typedef> {};
1676
1677template <typename InElementAllocator, typename InBitArrayAllocator>
1685
1686template <uint8 FromIndexSize, uint8 ToIndexSize> struct TCanMoveBetweenAllocators<TSizedDefaultAllocator<FromIndexSize>, TSizedDefaultAllocator<ToIndexSize>> : TCanMoveBetweenAllocators<typename TSizedDefaultAllocator<FromIndexSize>::Typedef, typename TSizedDefaultAllocator<ToIndexSize>::Typedef> {};
constexpr T Align(T Val, uint64 Alignment)
Definition AlignmentTemplates.h:18
#define FORCENOINLINE
Definition AndroidPlatform.h:142
#define checkSlow(expr)
Definition AssertionMacros.h:332
#define check(expr)
Definition AssertionMacros.h:314
UE_FORCEINLINE_HINT SizeType DefaultCalculateSlackReserve(SizeType NewMax, SIZE_T BytesPerElement, bool bAllowQuantize, uint32 Alignment=DEFAULT_ALIGNMENT)
Definition ContainerAllocationPolicies.h:223
#define NumBitsPerDWORD
Definition ContainerAllocationPolicies.h:1371
#define DEFAULT_MIN_NUMBER_OF_HASHED_ELEMENTS
Definition ContainerAllocationPolicies.h:1514
#define UE_CONTAINER_SLACK_GROWTH_FACTOR_DENOMINATOR
Definition ContainerAllocationPolicies.h:132
#define UE_CONTAINER_SLACK_GROWTH_FACTOR_NUMERATOR
Definition ContainerAllocationPolicies.h:124
UE_FORCEINLINE_HINT SizeType DefaultCalculateSlackShrink(SizeType NewMax, SizeType CurrentMax, SIZE_T BytesPerElement, bool bAllowQuantize, uint32 Alignment=DEFAULT_ALIGNMENT)
Definition ContainerAllocationPolicies.h:139
#define DEFAULT_NUMBER_OF_ELEMENTS_PER_HASH_BUCKET
Definition ContainerAllocationPolicies.h:1511
#define DEFAULT_BASE_NUMBER_OF_HASH_BUCKETS
Definition ContainerAllocationPolicies.h:1513
UE_FORCEINLINE_HINT SizeType DefaultCalculateSlackGrow(SizeType NewMax, SizeType CurrentMax, SIZE_T BytesPerElement, bool bAllowQuantize, uint32 Alignment=DEFAULT_ALIGNMENT)
Definition ContainerAllocationPolicies.h:169
@ INDEX_NONE
Definition CoreMiscDefines.h:150
EConstEval
Definition CoreMiscDefines.h:161
@ ConstEval
Definition CoreMiscDefines.h:161
#define UE_IF_CONSTEVAL
Definition Platform.h:786
FPlatformTypes::int16 int16
A 16-bit signed integer.
Definition Platform.h:1123
FPlatformTypes::int8 int8
An 8-bit signed integer.
Definition Platform.h:1121
FPlatformTypes::SIZE_T SIZE_T
An unsigned integer the same size as a pointer, the same as UPTRINT.
Definition Platform.h:1150
FPlatformTypes::TCHAR TCHAR
Either ANSICHAR or WIDECHAR, depending on whether the platform supports wide characters or the requir...
Definition Platform.h:1135
FPlatformTypes::int64 int64
A 64-bit signed integer.
Definition Platform.h:1127
FPlatformTypes::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
#define UE_FORCEINLINE_HINT
Definition Platform.h:723
#define UNLIKELY(x)
Definition Platform.h:857
FPlatformTypes::uint64 uint64
A 64-bit unsigned integer.
Definition Platform.h:1117
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
@ DEFAULT_ALIGNMENT
Definition MemoryBase.h:24
#define MAX_int32
Definition NumericLimits.h:25
uint8_t uint8
Definition binka_ue_file_header.h:8
uint16_t uint16
Definition binka_ue_file_header.h:7
uint32_t uint32
Definition binka_ue_file_header.h:6
Definition ContainerAllocationPolicies.h:284
Definition ContainerAllocationPolicies.h:267
@ RequireRangeCheck
Definition ContainerAllocationPolicies.h:276
int32 SizeType
Definition ContainerAllocationPolicies.h:270
ForElementType< FScriptContainerElement > ForAnyElementType
Definition ContainerAllocationPolicies.h:435
@ NeedsElementType
Definition ContainerAllocationPolicies.h:273
Definition ContainerAllocationPolicies.h:1644
TInlineAllocator< 4 > Typedef
Definition ContainerAllocationPolicies.h:1644
Definition ContainerAllocationPolicies.h:1643
TCompactSetAllocator Typedef
Definition ContainerAllocationPolicies.h:1643
Definition ContainerAllocationPolicies.h:1660
TSparseSetAllocator Typedef
Definition ContainerAllocationPolicies.h:1660
Definition ContainerAllocationPolicies.h:1645
TSparseArrayAllocator Typedef
Definition ContainerAllocationPolicies.h:1645
Definition ContainerAllocationPolicies.h:1642
TSparseSetAllocator Typedef
Definition ContainerAllocationPolicies.h:1642
Definition OutputDevice.h:133
Definition ContainerAllocationPolicies.h:455
SizeType GetInitialCapacity() const
Definition ContainerAllocationPolicies.h:550
UE_FORCEINLINE_HINT ~ForAnyElementType()
Definition ContainerAllocationPolicies.h:486
ForAnyElementType()
Definition ContainerAllocationPolicies.h:459
SIZE_T GetAllocatedSize(SizeType CurrentMax, SIZE_T NumBytesPerElement) const
Definition ContainerAllocationPolicies.h:540
void ResizeAllocation(SizeType CurrentNum, SizeType NewMax, SIZE_T NumBytesPerElement)
Definition ContainerAllocationPolicies.h:503
bool HasAllocation() const
Definition ContainerAllocationPolicies.h:545
UE_FORCEINLINE_HINT SizeType CalculateSlackGrow(SizeType NewMax, SizeType CurrentMax, SIZE_T NumBytesPerElement) const
Definition ContainerAllocationPolicies.h:535
UE_FORCEINLINE_HINT FScriptContainerElement * GetAllocation() const
Definition ContainerAllocationPolicies.h:499
UE_FORCEINLINE_HINT SizeType CalculateSlackReserve(SizeType NewMax, SIZE_T NumBytesPerElement) const
Definition ContainerAllocationPolicies.h:527
UE_FORCEINLINE_HINT SizeType CalculateSlackShrink(SizeType NewMax, SizeType CurrentMax, SIZE_T NumBytesPerElement) const
Definition ContainerAllocationPolicies.h:531
UE_FORCEINLINE_HINT void MoveToEmpty(ForAnyElementType &Other)
Definition ContainerAllocationPolicies.h:468
Definition ContainerAllocationPolicies.h:579
UE_FORCEINLINE_HINT ElementType * GetAllocation() const
Definition ContainerAllocationPolicies.h:589
ForElementType()
Definition ContainerAllocationPolicies.h:584
Definition ContainerAllocationPolicies.h:447
@ NeedsElementType
Definition ContainerAllocationPolicies.h:451
int32 SizeType
Definition ContainerAllocationPolicies.h:449
@ RequireRangeCheck
Definition ContainerAllocationPolicies.h:452
Definition ContainerAllocationPolicies.h:1392
InElementAllocator ElementAllocator
Definition ContainerAllocationPolicies.h:1394
InBitArrayAllocator BitArrayAllocator
Definition ContainerAllocationPolicies.h:1395
Definition ContainerAllocationPolicies.h:1286
UE_FORCEINLINE_HINT SizeType CalculateSlackShrink(SizeType NewMax, SizeType CurrentMax, SIZE_T NumBytesPerElement) const
Definition ContainerAllocationPolicies.h:1325
bool HasAllocation() const
Definition ContainerAllocationPolicies.h:1343
UE_FORCEINLINE_HINT SizeType CalculateSlackReserve(SizeType NewMax, SIZE_T NumBytesPerElement) const
Definition ContainerAllocationPolicies.h:1319
UE_FORCEINLINE_HINT SizeType CalculateSlackGrow(SizeType NewMax, SizeType CurrentMax, SIZE_T NumBytesPerElement) const
Definition ContainerAllocationPolicies.h:1331
ForElementType()
Definition ContainerAllocationPolicies.h:1290
void ResizeAllocation(SizeType CurrentNum, SizeType NewMax, SIZE_T NumBytesPerElement)
Definition ContainerAllocationPolicies.h:1313
SizeType GetInitialCapacity() const
Definition ContainerAllocationPolicies.h:1348
UE_FORCEINLINE_HINT void MoveToEmpty(ForElementType &Other)
Definition ContainerAllocationPolicies.h:1299
UE_FORCEINLINE_HINT ElementType * GetAllocation() const
Definition ContainerAllocationPolicies.h:1308
SIZE_T GetAllocatedSize(SizeType CurrentMax, SIZE_T NumBytesPerElement) const
Definition ContainerAllocationPolicies.h:1338
Definition ContainerAllocationPolicies.h:1276
int32 SizeType
Definition ContainerAllocationPolicies.h:1278
@ RequireRangeCheck
Definition ContainerAllocationPolicies.h:1281
@ NeedsElementType
Definition ContainerAllocationPolicies.h:1280
void ForAnyElementType
Definition ContainerAllocationPolicies.h:1367
@ ShrinkByDefault
Definition ContainerAllocationPolicies.h:1282
Definition ContainerAllocationPolicies.h:1666
TFixedSparseSetAllocator< N... > Typedef
Definition ContainerAllocationPolicies.h:1666
Definition ContainerAllocationPolicies.h:1419
TFixedAllocator< NumInlineElements > ElementAllocator
Definition ContainerAllocationPolicies.h:1427
TFixedAllocator< InlineBitArrayDWORDs > BitArrayAllocator
Definition ContainerAllocationPolicies.h:1428
Definition ContainerAllocationPolicies.h:1604
static UE_FORCEINLINE_HINT uint32 GetNumberOfHashBuckets(uint32 NumHashedElements)
Definition ContainerAllocationPolicies.h:1614
Definition ContainerAllocationPolicies.h:1664
TInlineSparseSetAllocator< N, S, NN... > Typedef
Definition ContainerAllocationPolicies.h:1664
Definition ContainerAllocationPolicies.h:1404
TInlineAllocator< NumInlineElements, typename SecondaryAllocator::ElementAllocator > ElementAllocator
Definition ContainerAllocationPolicies.h:1412
TInlineAllocator< InlineBitArrayDWORDs, typename SecondaryAllocator::BitArrayAllocator > BitArrayAllocator
Definition ContainerAllocationPolicies.h:1413
Definition ContainerAllocationPolicies.h:1567
static UE_FORCEINLINE_HINT uint32 GetNumberOfHashBuckets(uint32 NumHashedElements)
Definition ContainerAllocationPolicies.h:1577
Definition ContainerAllocationPolicies.h:1096
UE_FORCEINLINE_HINT SizeType CalculateSlackReserve(SizeType NewMax, SIZE_T NumBytesPerElement) const
Definition ContainerAllocationPolicies.h:1199
SizeType GetInitialCapacity() const
Definition ContainerAllocationPolicies.h:1227
UE_FORCEINLINE_HINT ElementType * GetAllocation() const
Definition ContainerAllocationPolicies.h:1148
UE_FORCEINLINE_HINT bool HasAllocation() const
Definition ContainerAllocationPolicies.h:1222
ForElementType()
Definition ContainerAllocationPolicies.h:1099
~ForElementType()
Definition ContainerAllocationPolicies.h:1105
UE_FORCEINLINE_HINT void MoveToEmpty(ForElementType &Other)
Definition ContainerAllocationPolicies.h:1122
SIZE_T GetAllocatedSize(SizeType CurrentMax, SIZE_T NumBytesPerElement) const
Definition ContainerAllocationPolicies.h:1217
UE_FORCEINLINE_HINT SizeType CalculateSlackShrink(SizeType NewMax, SizeType CurrentMax, SIZE_T NumBytesPerElement) const
Definition ContainerAllocationPolicies.h:1205
UE_FORCEINLINE_HINT SizeType CalculateSlackGrow(SizeType NewMax, SizeType CurrentMax, SIZE_T NumBytesPerElement) const
Definition ContainerAllocationPolicies.h:1211
void ResizeAllocation(SizeType CurrentNum, SizeType NewMax, SIZE_T NumBytesPerElement)
Definition ContainerAllocationPolicies.h:1153
Definition ContainerAllocationPolicies.h:1087
int32 SizeType
Definition ContainerAllocationPolicies.h:1089
@ NeedsElementType
Definition ContainerAllocationPolicies.h:1091
@ RequireRangeCheck
Definition ContainerAllocationPolicies.h:1092
void ForAnyElementType
Definition ContainerAllocationPolicies.h:1261
Definition ContainerAllocationPolicies.h:1662
TSparseSetAllocator< InSparseArrayAllocator, InHashAllocator, N... > Typedef
Definition ContainerAllocationPolicies.h:1662
Definition ContainerAllocationPolicies.h:830
TSizedHeapAllocator< IndexSize > Typedef
Definition ContainerAllocationPolicies.h:830
Definition ContainerAllocationPolicies.h:631
void ResizeAllocation(SizeType CurrentNum, SizeType NewMax, SIZE_T NumBytesPerElement, uint32 AlignmentOfElement)
Definition ContainerAllocationPolicies.h:725
constexpr SizeType GetInitialCapacity() const
Definition ContainerAllocationPolicies.h:785
UE_FORCEINLINE_HINT FScriptContainerElement * GetAllocation() const
Definition ContainerAllocationPolicies.h:696
bool HasAllocation() const
Definition ContainerAllocationPolicies.h:780
UE_FORCEINLINE_HINT SizeType CalculateSlackShrink(SizeType NewMax, SizeType CurrentMax, SIZE_T NumBytesPerElement) const
Definition ContainerAllocationPolicies.h:758
consteval ForAnyElementType(EConstEval)
Definition ContainerAllocationPolicies.h:642
UE_FORCEINLINE_HINT SizeType CalculateSlackReserve(SizeType NewMax, SIZE_T NumBytesPerElement) const
Definition ContainerAllocationPolicies.h:750
UE_FORCEINLINE_HINT SizeType CalculateSlackGrow(SizeType NewMax, SizeType CurrentMax, SIZE_T NumBytesPerElement) const
Definition ContainerAllocationPolicies.h:766
UE_FORCEINLINE_HINT SizeType CalculateSlackReserve(SizeType NewMax, SIZE_T NumBytesPerElement, uint32 AlignmentOfElement) const
Definition ContainerAllocationPolicies.h:754
UE_FORCEINLINE_HINT void MoveToEmpty(ForAnyElementType &Other)
Definition ContainerAllocationPolicies.h:677
void ResizeAllocation(SizeType CurrentNum, SizeType NewMax, SIZE_T NumBytesPerElement)
Definition ContainerAllocationPolicies.h:700
UE_FORCEINLINE_HINT SizeType CalculateSlackGrow(SizeType NewMax, SizeType CurrentMax, SIZE_T NumBytesPerElement, uint32 AlignmentOfElement) const
Definition ContainerAllocationPolicies.h:770
UE_FORCEINLINE_HINT SizeType CalculateSlackShrink(SizeType NewMax, SizeType CurrentMax, SIZE_T NumBytesPerElement, uint32 AlignmentOfElement) const
Definition ContainerAllocationPolicies.h:762
UE_FORCEINLINE_HINT ~ForAnyElementType()
Definition ContainerAllocationPolicies.h:683
SIZE_T GetAllocatedSize(SizeType CurrentMax, SIZE_T NumBytesPerElement) const
Definition ContainerAllocationPolicies.h:775
constexpr ForAnyElementType()
Definition ContainerAllocationPolicies.h:637
UE_FORCEINLINE_HINT void MoveToEmptyFromOtherAllocator(typename OtherAllocator::ForAnyElementType &Other)
Definition ContainerAllocationPolicies.h:653
Definition ContainerAllocationPolicies.h:814
UE_FORCEINLINE_HINT ElementType * GetAllocation() const
Definition ContainerAllocationPolicies.h:823
consteval ForElementType(EConstEval)
Definition ContainerAllocationPolicies.h:818
Definition ContainerAllocationPolicies.h:618
BaseMallocType BaseMalloc
Definition ContainerAllocationPolicies.h:621
@ NeedsElementType
Definition ContainerAllocationPolicies.h:627
typename TBitsToSizeType< IndexSize >::Type SizeType
Definition ContainerAllocationPolicies.h:620
@ RequireRangeCheck
Definition ContainerAllocationPolicies.h:628
Definition ContainerAllocationPolicies.h:906
bool HasAllocation() const
Definition ContainerAllocationPolicies.h:1026
UE_FORCEINLINE_HINT ElementType * GetAllocation() const
Definition ContainerAllocationPolicies.h:948
UE_FORCEINLINE_HINT SizeType CalculateSlackGrow(SizeType NewMax, SizeType CurrentMax, SIZE_T NumBytesPerElement) const
Definition ContainerAllocationPolicies.h:1006
UE_FORCEINLINE_HINT void MoveToEmpty(ForElementType &Other)
Definition ContainerAllocationPolicies.h:932
UE_FORCEINLINE_HINT SizeType CalculateSlackReserve(SizeType NewMax, SIZE_T NumBytesPerElement) const
Definition ContainerAllocationPolicies.h:992
constexpr SizeType GetInitialCapacity() const
Definition ContainerAllocationPolicies.h:1031
SIZE_T GetAllocatedSize(SizeType CurrentMax, SIZE_T NumBytesPerElement) const
Definition ContainerAllocationPolicies.h:1017
consteval ForElementType(EConstEval)
Definition ContainerAllocationPolicies.h:921
void ResizeAllocation(SizeType CurrentNum, SizeType NewMax, SIZE_T NumBytesPerElement)
Definition ContainerAllocationPolicies.h:957
UE_FORCEINLINE_HINT SizeType CalculateSlackShrink(SizeType NewMax, SizeType CurrentMax, SIZE_T NumBytesPerElement) const
Definition ContainerAllocationPolicies.h:999
constexpr ForElementType()
Definition ContainerAllocationPolicies.h:910
Definition ContainerAllocationPolicies.h:894
@ RequireRangeCheck
Definition ContainerAllocationPolicies.h:901
void ForAnyElementType
Definition ContainerAllocationPolicies.h:1063
@ NeedsElementType
Definition ContainerAllocationPolicies.h:900
@ ShrinkByDefault
Definition ContainerAllocationPolicies.h:902
typename TBitsToSizeType< IndexSize >::Type SizeType
Definition ContainerAllocationPolicies.h:896
Definition ContainerAllocationPolicies.h:835
@ ShrinkByDefault
Definition ContainerAllocationPolicies.h:838
TSizedHeapAllocator< IndexSize > Typedef
Definition ContainerAllocationPolicies.h:837
Definition ContainerAllocationPolicies.h:1383
InBitArrayAllocator BitArrayAllocator
Definition ContainerAllocationPolicies.h:1387
InElementAllocator ElementAllocator
Definition ContainerAllocationPolicies.h:1386
Definition ContainerAllocationPolicies.h:1525
InHashAllocator HashAllocator
Definition ContainerAllocationPolicies.h:1540
InSparseArrayAllocator SparseArrayAllocator
Definition ContainerAllocationPolicies.h:1539
static UE_FORCEINLINE_HINT uint32 GetNumberOfHashBuckets(uint32 NumHashedElements)
Definition ContainerAllocationPolicies.h:1529
Definition ContainerAllocationPolicies.h:875
Definition ContainerAllocationPolicies.h:1436
implementation
Definition PlayInEditorLoadingScope.h:8
consteval bool ShrinkByDefaultOr()
Definition ContainerAllocationPolicies.h:879
static constexpr UE_FORCEINLINE_HINT uint32 RoundUpToPowerOfTwo(uint32 Arg)
Definition GenericPlatformMath.h:833
static constexpr UE_FORCEINLINE_HINT T Max(T A, T B)
Definition GenericPlatformMath.h:963
static FORCENOINLINE CORE_API void Free(void *Original)
Definition UnrealMemory.cpp:685
static FORCENOINLINE CORE_API SIZE_T QuantizeSize(SIZE_T Count, uint32 Alignment=DEFAULT_ALIGNMENT)
Definition UnrealMemory.cpp:700
Definition ContainerAllocationPolicies.h:242
Definition ContainerAllocationPolicies.h:247
@ SupportsElementAlignment
Definition ContainerAllocationPolicies.h:250
@ SupportsSlackTracking
Definition ContainerAllocationPolicies.h:251
@ SupportsFreezeMemoryImage
Definition ContainerAllocationPolicies.h:249
@ IsZeroConstruct
Definition ContainerAllocationPolicies.h:248
Definition ContainerAllocationPolicies.h:256
int16 Type
Definition ContainerAllocationPolicies.h:611
int32 Type
Definition ContainerAllocationPolicies.h:612
int64 Type
Definition ContainerAllocationPolicies.h:613
int8 Type
Definition ContainerAllocationPolicies.h:610
Definition ContainerAllocationPolicies.h:605
Definition ContainerAllocationPolicies.h:261
@ Value
Definition ContainerAllocationPolicies.h:262
Definition ContainerAllocationPolicies.h:1453
static constexpr size_t Value
Definition ContainerAllocationPolicies.h:1454
Definition ContainerAllocationPolicies.h:1449
InElementAllocator ElementAllocator
Definition ContainerAllocationPolicies.h:1458
Definition ContainerAllocationPolicies.h:1497
static constexpr size_t AllocatorAlignof
Definition ContainerAllocationPolicies.h:1499
static constexpr size_t ElementAlignof
Definition ContainerAllocationPolicies.h:1498
static constexpr size_t Value
Definition ContainerAllocationPolicies.h:1500
Definition ContainerAllocationPolicies.h:1490
Definition ContainerAllocationPolicies.h:1480
static constexpr size_t AllocatorAlignof
Definition ContainerAllocationPolicies.h:1482
static constexpr size_t Value
Definition ContainerAllocationPolicies.h:1483
static constexpr size_t ElementAlignof
Definition ContainerAllocationPolicies.h:1481
Definition ContainerAllocationPolicies.h:1473
Definition NumericLimits.h:41
Definition TypeCompatibleBytes.h:24