UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
Pow2ChunkedArray.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#include "HAL/PlatformMath.h"
6#include "HAL/UnrealMemory.h"
7
8
10// FPow2ChunkedArray
11//
12// A chunk based array where each chunk is twice as large as the previous one.
13// Adding and accessing elements are O(1)
14// Add is threadsafe and keeping references is safe since it never reallocates
15
16template<typename T, uint32 MinSize = 16, uint32 MaxSize = 16777216>
18{
19public:
22
25
26 inline T& Add(const T& Value, uint32& OutIndex);
27 inline T& Add(const T& Value);
28 inline T& Add(T&& Value);
29
30 inline const T& operator[](uint32 Index) const;
32
33 inline uint32 Num() const;
34
35 inline const T& GetElementAt(uint32 Index) const;
36
37 inline void* AddUninitialized(uint32& OutIndex);
38
40 inline uint32 GetBucketStart(uint32 BucketIndex) const;
41 inline uint32 GetBucketSize(uint32 BucketIndex) const;
42
43private:
44 std::atomic<uint32> Size;
45 volatile int64 Buckets[BucketCount];
46};
47
48
50// Implementation
51
52template<typename T, uint32 MinSize, uint32 MaxSize>
57
58template<typename T, uint32 MinSize, uint32 MaxSize>
60{
62 for (uint32 BucketIndex=0; Left; ++BucketIndex)
63 {
64 T* Elements = reinterpret_cast<T*>(Buckets[BucketIndex]);
65 uint32 LeftInBucket = FPlatformMath::Min(Left, GetBucketSize(BucketIndex));
66 if (!std::is_trivially_destructible_v<T>)
67 {
68 for (uint32 I=0, E=LeftInBucket; I!=E; ++I)
69 {
70 Elements[I].~T();
71 }
72 }
74 FMemory::Free(Elements);
75 }
76}
77
78template<typename T, uint32 MinSize, uint32 MaxSize>
80{
81 return *new (AddUninitialized(OutIndex)) T(Value);
82}
83
84template<typename T, uint32 MinSize, uint32 MaxSize>
86{
87 uint32 OutIndex;
88 return *new (AddUninitialized(OutIndex)) T(Value);
89}
90
91template<typename T, uint32 MinSize, uint32 MaxSize>
93{
94 uint32 OutIndex;
95 return *new (AddUninitialized(OutIndex)) T(MoveTemp(Value));
96}
97
98template<typename T, uint32 MinSize, uint32 MaxSize>
100{
101 return GetElementAt(Index);
102}
103
104template<typename T, uint32 MinSize, uint32 MaxSize>
106{
107 return const_cast<T&>(GetElementAt(Index));
108}
109
110template<typename T, uint32 MinSize, uint32 MaxSize>
115
116template<typename T, uint32 MinSize, uint32 MaxSize>
118{
119 check(Index < Size);
120 uint32 BucketIndex = GetBucketIndex(Index);
121 uint32 BucketStart = GetBucketStart(BucketIndex);
123 return reinterpret_cast<const T*>(Buckets[BucketIndex])[BucketOffset];
124}
125
126template<typename T, uint32 MinSize, uint32 MaxSize>
128{
129 uint32 Index = Size++;
130 uint32 BucketIndex = GetBucketIndex(Index);
131
132 volatile int64& BucketRef = Buckets[BucketIndex];
133
134 int64 BucketRes = FPlatformAtomics::AtomicRead(&BucketRef);
135 if (!BucketRes)
136 {
137 void* NewPtr = FMemory::Malloc(GetBucketSize(BucketIndex) * sizeof(T), alignof(T));
138 BucketRes = FPlatformAtomics::InterlockedCompareExchange(&BucketRef, int64(NewPtr), 0);
139 if (BucketRes)
140 {
142 }
143 else
144 {
146 }
147 }
148
149 uint32 BucketStart = GetBucketStart(BucketIndex);
151
152 OutIndex = Index;
153
154 return reinterpret_cast<T*>(BucketRes) + BucketOffset;
155}
156
157template<typename T, uint32 MinSize, uint32 MaxSize>
159{
160 return uint32(FPlatformMath::FloorLog2(Index / 16 + 1));
161}
162
163template<typename T, uint32 MinSize, uint32 MaxSize>
165{
166 return BucketIndex ? 16 * ((1 << BucketIndex) - 1) : 0;
167}
168
169template<typename T, uint32 MinSize, uint32 MaxSize>
171{
172 return FPlatformMath::Max(MinSize, 1u << (BucketIndex + SkipCount));
173}
174
#define check(expr)
Definition AssertionMacros.h:314
FPlatformTypes::int64 int64
A 64-bit signed integer.
Definition Platform.h:1127
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
UE_INTRINSIC_CAST UE_REWRITE constexpr std::remove_reference_t< T > && MoveTemp(T &&Obj) noexcept
Definition UnrealTemplate.h:520
uint32 Size
Definition VulkanMemory.cpp:4034
uint32_t uint32
Definition binka_ue_file_header.h:6
Definition Pow2ChunkedArray.h:18
uint32 GetBucketSize(uint32 BucketIndex) const
Definition Pow2ChunkedArray.h:170
uint32 GetBucketStart(uint32 BucketIndex) const
Definition Pow2ChunkedArray.h:164
~FPow2ChunkedArray()
Definition Pow2ChunkedArray.h:59
T & operator[](uint32 Index)
Definition Pow2ChunkedArray.h:105
const T & GetElementAt(uint32 Index) const
Definition Pow2ChunkedArray.h:117
T & Add(const T &Value)
Definition Pow2ChunkedArray.h:85
FPow2ChunkedArray()
Definition Pow2ChunkedArray.h:53
T & Add(T &&Value)
Definition Pow2ChunkedArray.h:92
@ BucketCount
Definition Pow2ChunkedArray.h:21
@ SkipCount
Definition Pow2ChunkedArray.h:20
const T & operator[](uint32 Index) const
Definition Pow2ChunkedArray.h:99
uint32 Num() const
Definition Pow2ChunkedArray.h:111
void * AddUninitialized(uint32 &OutIndex)
Definition Pow2ChunkedArray.h:127
T & Add(const T &Value, uint32 &OutIndex)
Definition Pow2ChunkedArray.h:79
uint32 GetBucketIndex(uint32 Index) const
Definition Pow2ChunkedArray.h:158
U16 Index
Definition radfft.cpp:71
static constexpr uint32 CeilLogTwo(uint32 Arg)
Definition GenericPlatformMath.h:800
static FORCENOINLINE CORE_API void Free(void *Original)
Definition UnrealMemory.cpp:685
static UE_FORCEINLINE_HINT void * Memset(void *Dest, uint8 Char, SIZE_T Count)
Definition UnrealMemory.h:119