5#include "Containers/ContainerAllocationPolicies.h"
6#include "Containers/ContainerAllocationPolicies.h"
8#include "HAL/PlatformAtomics.h"
9#include "HAL/PlatformCrt.h"
10#include "HAL/UnrealMemory.h"
11#include "Math/UnrealMathUtility.h"
12#include "Misc/AssertionMacros.h"
13#include "Serialization/MemoryImageWriter.h"
14#include "Serialization/MemoryImageWriter.h"
15#include "Serialization/MemoryLayout.h"
16#include "Templates/ChooseClass.h"
17#include "Templates/UnrealTemplate.h"
19#include <initializer_list>
39 Hash *= 0xff51afd7ed558ccdull;
41 Hash *= 0xc4ceb9fe1a85ec53ull;
49 for(
auto Element : InitList )
51 Element *= 0xcc9e2d51;
52 Element = ( Element << 15 ) | ( Element >> (32 - 15) );
53 Element *= 0x1b873593;
56 Hash = ( Hash << 13 ) | ( Hash >> (32 - 13) );
57 Hash = Hash * 5 + 0xe6546b64;
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78template< uint16 HashSize, uint16 IndexSize >
89 uint16
First( uint16 Key )
const;
90 uint16
Next( uint16 Index )
const;
91 bool IsValid( uint16 Index )
const;
93 void Add( uint16 Key, uint16 Index );
94 void Remove( uint16 Key, uint16 Index );
101template< uint16 HashSize, uint16 IndexSize >
104 static_assert( ( HashSize & (HashSize - 1) ) == 0,
"Hash size must be power of 2" );
105 static_assert( IndexSize - 1 < 0xffff,
"Index 0xffff is reserved" );
109template< uint16 HashSize, uint16 IndexSize >
112 static_assert((HashSize & (HashSize - 1)) == 0,
"Hash size must be power of 2");
113 static_assert(IndexSize - 1 < 0xffff,
"Index 0xffff is reserved");
116template< uint16 HashSize, uint16 IndexSize >
119 FMemory::Memset( Hash, 0xff, HashSize * 2 );
123template< uint16 HashSize, uint16 IndexSize >
131template< uint16 HashSize, uint16 IndexSize >
135 return NextIndex[ Index ];
138template< uint16 HashSize, uint16 IndexSize >
141 return Index != 0xffff;
144template< uint16 HashSize, uint16 IndexSize >
150 NextIndex[ Index ] = Hash[ Key ];
154template< uint16 HashSize, uint16 IndexSize >
161 if( Hash[Key] == Index )
164 Hash[Key] = NextIndex[ Index ];
168 for( uint16 i = Hash[Key]; IsValid(i); i = NextIndex[i] )
170 if( NextIndex[i] == Index )
173 NextIndex[i] = NextIndex[ Index ];
181
182
183
184
185
186
187
188
189
190
191
192
193
194
198 FHashTable( uint32 InHashSize = 1024, uint32 InIndexSize = 0 );
203 void Clear( uint32 InHashSize, uint32 InIndexSize = 0 );
208 uint32
First( uint32 Key )
const;
209 uint32
Next( uint32 Index )
const;
210 bool IsValid( uint32 Index )
const;
212 void Add( uint32 Key, uint32 Index );
214 void Remove( uint32 Key, uint32 Index );
239 check( HashSize > 0 );
240 check( FMath::IsPowerOfTwo( HashSize ) );
289 check( HashSize > 0 );
290 check( FMath::IsPowerOfTwo( HashSize ) );
342 Resize( FMath::Max< uint32 >( 32u, FMath::RoundUpToPowerOfTwo( Index + 1 ) ) );
355 check( Index < IndexSize );
370 if(
Hash[Key] == Index )
389template<
typename InAllocator>
393 using Allocator = InAllocator;
395 using ElementAllocatorType =
typename TChooseClass<
396 Allocator::NeedsElementType,
397 typename Allocator::
template ForElementType<uint32>,
398 typename Allocator::ForAnyElementType
401 explicit THashTable(uint32 InHashSize = 1024, uint32 InIndexSize = 0);
411 void Resize(uint32 NewIndexSize);
416 uint32
First(uint16 Key)
const;
417 uint32
Next(uint32 Index)
const;
418 bool IsValid(uint32 Index)
const;
420 void Add(uint16 Key, uint32 Index);
421 void Remove(uint16 Key, uint32 Index);
465template<
typename InAllocator>
467 : HashMask(InHashSize - 1u)
468 , IndexSize(InIndexSize)
470 check(InHashSize > 0u && InHashSize <= 0x10000);
471 check(FMath::IsPowerOfTwo(InHashSize));
473 Hash.ResizeAllocation(0, InHashSize,
sizeof(uint32));
474 FMemory::Memset(Hash.GetAllocation(), 0xff, InHashSize * 4);
478 NextIndex.ResizeAllocation(0, IndexSize,
sizeof(uint32));
482template<
typename InAllocator>
487template<
typename InAllocator>
490 Hash.MoveToEmpty(Other.Hash);
491 NextIndex.MoveToEmpty(Other.NextIndex);
492 HashMask = Other.HashMask;
493 IndexSize = Other.IndexSize;
495 Other.IndexSize = 0u;
499template<
typename InAllocator>
504 FMemory::Memset(Hash.GetAllocation(), 0xff, (HashMask + 1u) * 4);
509template<
typename InAllocator>
517template<
typename InAllocator>
521 const uint32 Next = NextIndexAt(Index);
526template<
typename InAllocator>
532template<
typename InAllocator>
535 if (Index >= IndexSize)
537 Resize(FMath::Max<uint32>(32u, FMath::RoundUpToPowerOfTwo(Index + 1)));
541 NextIndexAt(Index) = HashAt(Key);
545template<
typename InAllocator>
548 if (Index >= IndexSize)
554 if (HashAt(Key) == Index)
557 HashAt(Key) = NextIndexAt(Index);
561 for (uint32 i = HashAt(Key); IsValid(i); i = NextIndexAt(i))
563 if (NextIndexAt(i) == Index)
566 NextIndexAt(i) = NextIndexAt(Index);
573template<
typename InAllocator>
576 if (NewIndexSize != IndexSize)
578 NextIndex.ResizeAllocation(IndexSize, NewIndexSize,
sizeof(uint32));
579 IndexSize = NewIndexSize;
585 template<
typename InAllocator>
591 template<
typename InAllocator>
598 template<
typename InAllocator>
604 template<
typename InAllocator>
static FORCEINLINE uint32 Murmur32(std::initializer_list< uint32 > InitList)
static FORCEINLINE uint64 MurmurFinalize64(uint64 Hash)
static FORCEINLINE uint32 MurmurFinalize32(uint32 Hash)
#define DECLARE_TEMPLATE_INTRINSIC_TYPE_LAYOUT(TemplatePrefix, T)
float AverageSearch() const
static uint32 EmptyHash[1]
uint32 Next(uint32 Index) const
void Clear(uint32 InHashSize, uint32 InIndexSize=0)
void Add(uint32 Key, uint32 Index)
void Remove(uint32 Key, uint32 Index)
FHashTable(uint32 InHashSize=1024, uint32 InIndexSize=0)
void Resize(uint32 NewIndexSize)
void Add_Concurrent(uint32 Key, uint32 Index)
bool IsValid(uint32 Index) const
uint32 First(uint32 Key) const
FHashTable(const FHashTable &Other)
THashTable(uint32 InHashSize=1024, uint32 InIndexSize=0)
THashTable & MoveAssign(THashTable &&Other)
uint32 First(uint16 Key) const
FORCEINLINE uint32 HashAt(uint32 Index) const
THashTable(const THashTable &Other)=delete
THashTable & operator=(const THashTable &Other)=delete
void CopyUnfrozen(const FMemoryUnfreezeContent &Context, void *Dst) const
bool IsValid(uint32 Index) const
ElementAllocatorType Hash
void Remove(uint16 Key, uint32 Index)
FORCEINLINE uint32 & NextIndexAt(uint32 Index)
THashTable(THashTable &&Other)
const uint32 * GetNextIndices() const
ElementAllocatorType NextIndex
FORCEINLINE uint32 NextIndexAt(uint32 Index) const
void Resize(uint32 NewIndexSize)
uint32 Next(uint32 Index) const
FORCEINLINE uint32 & HashAt(uint32 Index)
void WriteMemoryImage(FMemoryImageWriter &Writer) const
THashTable & operator=(THashTable &&Other)
void Add(uint16 Key, uint32 Index)
uint16 Next(uint16 Index) const
uint16 NextIndex[IndexSize]
TStaticHashTable(ENoInit)
bool IsValid(uint16 Index) const
void Add(uint16 Key, uint16 Index)
uint16 First(uint16 Key) const
void Remove(uint16 Key, uint16 Index)
uint32 IntrinsicAppendHash(const THashTable< InAllocator > *DummyObject, const FTypeLayoutDesc &TypeDesc, const FPlatformTypeLayoutParameters &LayoutParams, FSHA1 &Hasher)
uint32 IntrinsicUnfrozenCopy(const FMemoryUnfreezeContent &Context, const THashTable< InAllocator > &Object, void *OutDst)
void IntrinsicWriteMemoryImage(FMemoryImageWriter &Writer, const THashTable< InAllocator > &Object, const FTypeLayoutDesc &)
uint32 IntrinsicGetTargetAlignment(const THashTable< InAllocator > *DummyObject, const FTypeLayoutDesc &TypeDesc, const FPlatformTypeLayoutParameters &LayoutParams)
static FORCEINLINE void * Memset(void *Dest, uint8 Char, SIZE_T Count)
static FORCEINLINE void * Memcpy(void *Dest, const void *Src, SIZE_T Count)