UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
RobinHoodHashTable.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2#pragma once
3
4// Implementation of Robin Hood hash table.
5#include "CoreMinimal.h"
6#include "Containers/Map.h"
8
9#define RUN_HASHTABLE_CONCURENCY_CHECKS UE_BUILD_DEBUG
10
11#if RUN_HASHTABLE_CONCURENCY_CHECKS
12#define CHECK_CONCURRENT_ACCESS(x) check(x)
13#else
14#define CHECK_CONCURRENT_ACCESS(x)
15#endif
16
17namespace Experimental
18{
19
20namespace RobinHoodHashTable_Private
21{
22 template<typename, typename, typename, typename>
24}
25
27{
28public:
29 explicit FHashType() : Hash(InvalidHash) {}
30
31 inline bool operator == (FHashType Other) const
32 {
33 return Hash == Other.Hash;
34 }
35
36 inline bool operator != (FHashType Other) const
37 {
38 return Hash != Other.Hash;
39 }
40
41 using IntType = uint32;
42
43 inline IntType AsUInt() const
44 {
45 return Hash;
46 }
47
48private:
49 template<typename, typename, typename, typename>
51
52 inline explicit FHashType(IntType InHash) : Hash(InHash)
53 {
54 checkSlow(!(InHash & InvalidHash));
55 }
56
57 inline bool IsOccupied() const
58 {
59 return Hash != InvalidHash;
60 }
61
62 inline bool IsFree() const
63 {
64 return Hash == InvalidHash;
65 }
66
67 static constexpr const IntType InvalidHash = (IntType(1)) << (sizeof(IntType) * 8 - 1);
69};
70
72{
73public:
76
77 inline int32 GetIndex() const
78 {
79 return Index;
80 }
81
82 inline bool IsValid() const
83 {
84 return Index != INDEX_NONE;
85 }
86
88 {
89 return Index == InHashElementId.Index;
90 }
91
92private:
94};
95
96namespace RobinHoodHashTable_Private
97{
98 template<typename AllocatorType>
99 class TFreeList
100 {
101 using IndexType = int32;
102
103 struct FSpan
104 {
105 IndexType Start;
106 IndexType End;
107 };
108
110 int32 NumElements = 0;
111
112 public:
113 TFreeList()
114 {
115 Empty();
116 }
117
118 void Push(IndexType NodeIndex)
119 {
120 ++NumElements;
121
122 //find the index that points to our right side node
123 int Index = 1; //exclude the dummy
124 int Size = FreeList.Num() - 1;
125
126 //start with binary search for larger lists
127 while (Size > 32)
128 {
129 const int LeftoverSize = Size % 2;
130 Size = Size / 2;
131
132 const int CheckIndex = Index + Size;
133 const int IndexIfLess = CheckIndex + LeftoverSize;
134
135 Index = FreeList[CheckIndex].Start > NodeIndex ? IndexIfLess : Index;
136 }
137
138 //small size array optimization
139 int ArrayEnd = FMath::Min(Index + Size + 1, FreeList.Num());
140 while (Index < ArrayEnd)
141 {
142 if (FreeList[Index].Start < NodeIndex)
143 {
144 break;
145 }
146 Index++;
147 }
148
149 //can we merge with the right node
150 if (Index < FreeList.Num() && FreeList[Index].End + 1 == NodeIndex)
151 {
152 FreeList[Index].End = NodeIndex;
153
154 //are we filling the gap between the left and right node
155 if (FreeList[Index - 1].Start - 1 == NodeIndex)
156 {
157 FreeList[Index - 1].Start = FreeList[Index].Start;
158 FreeList.RemoveAt(Index);
159 }
160 return;
161 }
162
163 //can we merge with the left node
164 if (FreeList[Index - 1].Start - 1 == NodeIndex)
165 {
166 FreeList[Index - 1].Start = NodeIndex;
167 return;
168 }
169
170 //we are node that could not be merged
171 FreeList.Insert(FSpan{ NodeIndex , NodeIndex }, Index);
172 }
173
174 IndexType Pop()
175 {
176 --NumElements;
177
178 FSpan& Span = FreeList.Last();
179 IndexType Index = Span.Start;
181 if (Span.Start == Span.End)
182 {
183 FreeList.Pop();
184 return Index;
185 }
186 else
187 {
188 Span.Start++;
189 return Index;
190 }
191 }
192
193 bool Contains(IndexType Index) const
194 {
195 for (int i = FreeList.Num() - 1; i > -0; i--)
196 {
197 const FSpan& Span = FreeList[i];
198 if (Index >= Span.Start && Index <= Span.End)
199 {
200 return true;
201 }
202 }
203 return false;
204 }
205
206 void Empty()
207 {
208 FreeList.Reset(1);
209 //push a dummy
210 FreeList.Push(FSpan{ INDEX_NONE, INDEX_NONE });
211 NumElements = 0;
212 }
213
214 int Num() const
215 {
216 return NumElements;
217 }
218
220 {
221 return FreeList.GetAllocatedSize();
222 }
223 };
224
225 struct FUnitType
226 {
227 };
228
229 template<typename KeyType, typename ValueType>
230 class TKeyValue
231 {
232 using FindValueType = ValueType*;
233 using FindValueTypeConst = const ValueType *;
234 using ElementType = TPair<const KeyType, ValueType>;
235
236 template<typename, typename, typename, typename>
237 friend class TRobinHoodHashTable;
238
239 template<typename DeducedKeyType, typename DeducedValueType>
240 inline TKeyValue(DeducedKeyType&& InKey, DeducedValueType&& InVal)
242 , Forward<DeducedValueType>(InVal))
243 {
244 }
245
246 ElementType Pair;
247
248 inline FindValueType FindImpl()
249 {
250 return &Pair.Value;
251 }
252
253 inline FindValueTypeConst FindImpl() const
254 {
255 return &Pair.Value;
256 }
257
258 template<typename DeducedValueType>
259 inline void Update(DeducedValueType&& InValue)
260 {
262 }
263
264 inline ElementType& GetElement()
265 {
266 return Pair;
267 }
268
269 inline const ElementType& GetElement() const
270 {
271 return Pair;
272 }
273
274 inline const KeyType& GetKey() const
275 {
276 return Pair.Key;
277 }
278 };
279
280 template<typename KeyType>
281 class TKeyValue<KeyType, FUnitType>
282 {
283 using FindValueType = const KeyType*;
284 using FindValueTypeConst = FindValueType;
285 using ElementType = const KeyType;
286
287 template<typename, typename, typename, typename>
288 friend class TRobinHoodHashTable;
289
290 template<typename DeducedKeyType>
291 inline TKeyValue(DeducedKeyType&& InKey, FUnitType&&)
293 {
294 }
295
296 ElementType Key;
297
298 inline FindValueType FindImpl() const
299 {
300 return &Key;
301 }
302
303 inline ElementType& GetElement() const
304 {
305 return Key;
306 }
307
308 inline const KeyType& GetKey() const
309 {
310 return Key;
311 }
312 };
313
314 template<typename KeyType, typename ValueType, typename Hasher, typename HashMapAllocator>
316 {
317 protected:
319 using KeyValueType = RobinHoodHashTable_Private::TKeyValue<KeyType, ValueType>;
320 using FindValueType = typename KeyValueType::FindValueType;
321 using FindValueTypeConst = typename KeyValueType::FindValueTypeConst;
325
326 static constexpr const IndexType LoadFactorDivisor = 3;
327 static constexpr const IndexType LoadFactorQuotient = 5;
328 static constexpr const IndexType InvalidIndex = ~IndexType(0);
329
330 struct FData
331 {
332 FData() = default;
333 FData(const FData&) = default;
334 FData& operator=(const FData&) = default;
336 {
337 Empty();
338 }
339
341 {
342 return KeyVals.GetAllocatedSize() + FreeList.GetAllocatedSize();
343 }
344
345 template<typename DeducedKeyType, typename DeducedValueType>
347 {
348 CHECK_CONCURRENT_ACCESS(FPlatformAtomics::InterlockedIncrement(&ConcurrentWriters) == 1);
349 CHECK_CONCURRENT_ACCESS(FPlatformAtomics::InterlockedIncrement(&ConcurrentReaders) == 1);
351 if (FreeList.Num() > 0)
352 {
353 Index = FreeList.Pop();
355 Hashes[Index] = Hash;
356
357 }
358 else
359 {
360 Index = KeyVals.Num();
362 Hashes.Push(Hash);
363 }
365 CHECK_CONCURRENT_ACCESS(FPlatformAtomics::InterlockedDecrement(&ConcurrentReaders) == 0);
366 CHECK_CONCURRENT_ACCESS(FPlatformAtomics::InterlockedDecrement(&ConcurrentWriters) == 0);
367 return Index;
368 }
369
371 {
372 CHECK_CONCURRENT_ACCESS(FPlatformAtomics::InterlockedIncrement(&ConcurrentWriters) == 1);
373 CHECK_CONCURRENT_ACCESS(FPlatformAtomics::InterlockedIncrement(&ConcurrentReaders) == 1);
374 FreeList.Push(Index);
376 KeyVals[Index].~KeyValueType();
377#if RUN_HASHTABLE_CONCURENCY_CHECKS
378 memset(&KeyVals[Index], 0, sizeof(KeyValueType));
379#endif
380 CHECK_CONCURRENT_ACCESS(FPlatformAtomics::InterlockedDecrement(&ConcurrentReaders) == 0);
381 CHECK_CONCURRENT_ACCESS(FPlatformAtomics::InterlockedDecrement(&ConcurrentWriters) == 0);
382 //TODO shrink KeyValue Array.
383 //As the FreeList is sorted backwards this would work as follows:
384 // - go though the FreeList front to back as long as the FreeList entry is the last
385 // - than pop-off the last KeyValue WITHOUT calling its destructor again
386 // - remove the entry from the FreeList (probably remove the entire span at the end of iteration, as its tail would need to be moved)
387 }
388
389 inline bool Contains(IndexType Index) const
390 {
391 return Index < (IndexType)KeyVals.Num() && !FreeList.Contains(Index);
392 }
393
394 inline const KeyValueType& Get(IndexType Index) const
395 {
397 CHECK_CONCURRENT_ACCESS(FPlatformAtomics::InterlockedIncrement(&ConcurrentReaders) >= 1);
399 CHECK_CONCURRENT_ACCESS(FPlatformAtomics::InterlockedDecrement(&ConcurrentReaders) >= 0);
401 return KeyVals[Index];
402 }
403
405 {
407 CHECK_CONCURRENT_ACCESS(FPlatformAtomics::InterlockedIncrement(&ConcurrentReaders) >= 1);
409 CHECK_CONCURRENT_ACCESS(FPlatformAtomics::InterlockedDecrement(&ConcurrentReaders) >= 0);
411 return KeyVals[Index];
412 }
413
414 inline SizeType Num() const
415 {
416 return SizeType(KeyVals.Num()) - SizeType(FreeList.Num());
417 }
418
419 inline IndexType GetMaxIndex() const
420 {
421 return KeyVals.Num();
422 }
423
425 {
427
428 inline bool operator ==(const FIteratorState& Rhs) const
429 {
430 return Index == Rhs.Index;
431 }
432
433 inline bool operator !=(const FIteratorState& Rhs) const
434 {
435 return Index != Rhs.Index;
436 }
437 };
438
440 {
441 for (;;)
442 {
443 State.Index = (State.Index + 1) & InvalidIndex;
444 if (State.Index >= uint32(KeyVals.Num()) || Hashes[State.Index].IsOccupied())
445 {
446 return FIteratorState{ State.Index };
447 }
448 }
449 }
450
451 inline FIteratorState Start() const
452 {
454 }
455
456 inline FIteratorState End() const
457 {
458 return FIteratorState{ IndexType(KeyVals.Num()) };
459 }
460
461 void Empty()
462 {
463 FIteratorState Iter = Start();
465 while (Iter != EndIter)
466 {
467 KeyVals[Iter.Index].~KeyValueType();
468 Iter = Next(Iter);
469 }
471 KeyVals.Empty();
472 FreeList.Empty();
473 Hashes.Empty();
474 }
475
480
481#if RUN_HASHTABLE_CONCURENCY_CHECKS
482 mutable int ConcurrentReaders = 0;
483 mutable int ConcurrentWriters = 0;
484#endif
488 };
489
491 {
492 return HashValue & SizePow2Minus1;
493 }
494
496 {
497 IndexType InsertIndex = Index;
499 IndexType CurrentBucket = ModTableSize(Hash.AsUInt());
501 for (;;)
502 {
503 IndexType OtherDistance = ModTableSize(CurrentBucket - HashData[CurrentBucket].AsUInt());
504
505 checkSlow(HashData[CurrentBucket].IsFree() || OtherDistance <= MaximumDistance);
506 checkSlow(CurrentBucket == (ModTableSize(ModTableSize(HashData[CurrentBucket].AsUInt()) + OtherDistance)));
507
508 if (HashData[CurrentBucket].IsFree())
509 {
510 if (InsertDistance > MaximumDistance)
511 {
512 MaximumDistance = InsertDistance;
513 }
514
515 IndexData[CurrentBucket] = InsertIndex;
516 HashData[CurrentBucket] = InsertHash;
517 break;
518 }
519 else if (OtherDistance < InsertDistance)
520 {
521 if (InsertDistance > MaximumDistance)
522 {
523 MaximumDistance = InsertDistance;
524 }
525
526 IndexType OtherIndex = IndexData[CurrentBucket];
527 FHashType OtherHash = HashData[CurrentBucket];
528 IndexData[CurrentBucket] = InsertIndex;
529 HashData[CurrentBucket] = InsertHash;
530
532 InsertIndex = OtherIndex;
534 }
536 CurrentBucket = ModTableSize(CurrentBucket + 1);
537 }
538 }
539
540 private:
541 template<bool UpdateValue, typename DeducedKeyType, typename DeducedValueType>
542 inline FHashElementId FindOrUpdateIdByHashInternal(FHashType HashValue, DeducedKeyType&& Key, DeducedValueType&& Val, bool& bIsAlreadyInMap)
543 {
544 CHECK_CONCURRENT_ACCESS(FPlatformAtomics::InterlockedIncrement(&ConcurrentWriters) == 1);
545 CHECK_CONCURRENT_ACCESS(FPlatformAtomics::InterlockedIncrement(&ConcurrentReaders) == 1);
546
548 IndexType BucketIndex = ModTableSize(HashValue.AsUInt());
549 const IndexType EndBucketIndex = ModTableSize(HashValue.AsUInt() + MaximumDistance + 1);
550 do
551 {
552 if (HashValue == HashData[BucketIndex])
553 {
554 if (Hasher::Matches(Key, KeyValueData.Get(IndexData[BucketIndex]).GetKey()))
555 {
556 CHECK_CONCURRENT_ACCESS(FPlatformAtomics::InterlockedDecrement(&ConcurrentReaders) == 0);
557 CHECK_CONCURRENT_ACCESS(FPlatformAtomics::InterlockedDecrement(&ConcurrentWriters) == 0);
558 bIsAlreadyInMap = true;
559 if constexpr (UpdateValue)
560 {
561 KeyValueData.Get(IndexData[BucketIndex]).Update(Forward<DeducedValueType>(Val));
562 }
563 return IndexData[BucketIndex];
564 }
565 }
566
567 BucketIndex = ModTableSize(BucketIndex + 1);
568 } while (BucketIndex != EndBucketIndex);
569
570 if ((KeyValueData.Num() * LoadFactorQuotient) >= (SizePow2Minus1 * LoadFactorDivisor))
571 {
574 IndexType OldSizePow2Minus1 = SizePow2Minus1;
575 SizePow2Minus1 = SizePow2Minus1 * 2 + 1;
576 MaximumDistance = 0;
577 IndexData.Reserve(SizePow2Minus1 + 1);
578 IndexData.AddUninitialized(SizePow2Minus1 + 1);
579 HashData.Reserve(SizePow2Minus1 + 1);
580 HashData.AddDefaulted(SizePow2Minus1 + 1);
581
583 {
584 if (HashDataOld[Index].IsOccupied())
585 {
587 }
588 }
589 }
590
592 InsertIntoTable(InsertIndex, HashValue);
593
594 CHECK_CONCURRENT_ACCESS(FPlatformAtomics::InterlockedDecrement(&ConcurrentReaders) == 0);
595 CHECK_CONCURRENT_ACCESS(FPlatformAtomics::InterlockedDecrement(&ConcurrentWriters) == 0);
596
597 bIsAlreadyInMap = false;
598 return FHashElementId(InsertIndex);
599 }
600
601 protected:
602 template<typename DeducedKeyType, typename DeducedValueType>
607
608 template<typename DeducedKeyType, typename DeducedValueType>
614
615 template<typename DeducedKeyType, typename DeducedValueType>
617 {
619 return KeyValueData.Get(Id.GetIndex()).FindImpl();
620 }
621
622 template<typename DeducedKeyType, typename DeducedValueType>
627
628 template<typename DeducedKeyType, typename DeducedValueType>
634
635 template<typename DeducedKeyType, typename DeducedValueType>
637 {
639 return KeyValueData.Get(Id.GetIndex()).FindImpl();
640 }
641
643 {
644 IndexData.Reserve(1); IndexData.AddUninitialized();
645 HashData.Reserve(1); HashData.AddDefaulted();
646 }
647
649 {
650 SizePow2Minus1 = Other.SizePow2Minus1;
651 MaximumDistance = Other.MaximumDistance;
652 KeyValueData = Other.KeyValueData;
653
654 IndexData.Reserve(SizePow2Minus1 + 1);
655 IndexData.AddUninitialized(SizePow2Minus1 + 1);
656 HashData.Reserve(SizePow2Minus1 + 1);
657 HashData.AddUninitialized(SizePow2Minus1 + 1);
658
659 for (uint32 Idx = 0; Idx <= SizePow2Minus1; Idx++)
660 {
661 IndexData[Idx] = Other.IndexData[Idx];
662 HashData[Idx] = Other.HashData[Idx];
663 }
664 }
665
667 {
668 if (this != &Other)
669 {
670 SizePow2Minus1 = Other.SizePow2Minus1;
671 MaximumDistance = Other.MaximumDistance;
672 KeyValueData = Other.KeyValueData;
673
674 IndexData.Reserve(SizePow2Minus1 + 1);
675 IndexData.AddUninitialized(SizePow2Minus1 + 1);
676 HashData.Reserve(SizePow2Minus1 + 1);
677 HashData.AddUninitialized(SizePow2Minus1 + 1);
678
679 for (uint32 Idx = 0; Idx <= SizePow2Minus1; Idx++)
680 {
681 IndexData[Idx] = Other.IndexData[Idx];
682 HashData[Idx] = Other.HashData[Idx];
683 }
684 }
685
686 return *this;
687 }
688
690 {
691 SizePow2Minus1 = Other.SizePow2Minus1;
692 MaximumDistance = Other.MaximumDistance;
693 KeyValueData = MoveTemp(Other.KeyValueData);
694
695 IndexData = MoveTemp(Other.IndexData);
696 HashData = MoveTemp(Other.HashData);
697
698 Other.Empty();
699 }
700
702 {
703 if (this != &Other)
704 {
705 SizePow2Minus1 = Other.SizePow2Minus1;
706 MaximumDistance = Other.MaximumDistance;
707 KeyValueData = MoveTemp(Other.KeyValueData);
708
709 IndexData = MoveTemp(Other.IndexData);
710 HashData = MoveTemp(Other.HashData);
711
712 Other.Empty();
713 }
714
715 return *this;
716 }
717
718 public:
719 inline static FHashType ComputeHash(const KeyType& Key)
720 {
721 typename FHashType::IntType HashValue = Hasher::GetKeyHash(Key);
722 constexpr typename FHashType::IntType HashBits = (~(1 << (sizeof(typename FHashType::IntType) * 8 - 1)));
723 return FHashType(HashValue & HashBits);
724 }
725
727 {
728 typename FData::FIteratorState State;
729 FData& Data;
730
731 template<typename, typename, typename, typename>
733
734 inline FIteratorType(FData& InData, bool bIsStartIterator) : Data(InData)
735 {
737 {
738 State = Data.Start();
739 }
740 else
741 {
742 State = Data.End();
743 }
744 }
745
746 public:
747 inline bool operator ==(const FIteratorType& Rhs) const
748 {
749 return State == Rhs.State && &Data == &Rhs.Data;
750 }
751
752 inline bool operator !=(const FIteratorType& Rhs) const
753 {
754 return State != Rhs.State || &Data != &Rhs.Data;
755 }
756
757 inline ElementType& operator*() const
758 {
759 return Data.Get(State.Index).GetElement();
760 }
761
763 {
764 State = Data.Next(State);
765 return *this;
766 }
767
769 {
770 return FHashElementId(State.Index);
771 }
772 };
773
775 {
776 return FIteratorType(KeyValueData, true);
777 }
778
780 {
781 return FIteratorType(KeyValueData, false);
782 }
783
785 {
786 typename FData::FIteratorState State;
787 const FData& Data;
788
789 template<typename, typename, typename, typename>
791
792 inline FConstIteratorType(const FData& InData, bool bIsStartIterator) : Data(InData)
793 {
795 {
796 State = Data.Start();
797 }
798 else
799 {
800 State = Data.End();
801 }
802 }
803
804 public:
805 inline bool operator ==(const FConstIteratorType& Rhs) const
806 {
807 return State == Rhs.State && &Data == &Rhs.Data;
808 }
809
810 inline bool operator !=(const FConstIteratorType& Rhs) const
811 {
812 return State != Rhs.State || &Data != &Rhs.Data;
813 }
814
815 inline const ElementType& operator*() const
816 {
817 return Data.Get(State.Index).GetElement();
818 }
819
821 {
822 State = Data.Next(State);
823 return *this;
824 }
825
827 {
828 return FHashElementId(State.Index);
829 }
830 };
831
833 {
834 return FConstIteratorType(KeyValueData, true);
835 }
836
837 inline FConstIteratorType end() const
838 {
839 return FConstIteratorType(KeyValueData, false);
840 }
841
843 {
844 return KeyValueData.GetAllocatedSize() + IndexData.GetAllocatedSize() + HashData.GetAllocatedSize();
845 }
846
847 inline int32 Num() const
848 {
849 return (int32)KeyValueData.Num();
850 }
851
852 inline IndexType GetMaxIndex() const
853 {
854 return KeyValueData.GetMaxIndex();
855 }
856
858 {
859 return KeyValueData.Get(Id.GetIndex()).GetElement();
860 }
861
863 {
864 return KeyValueData.Get(Id.GetIndex()).GetElement();
865 }
866
868 {
869 return KeyValueData.Contains(Id.GetIndex());
870 }
871
872 inline FHashElementId FindIdByHash(const FHashType HashValue, const KeyType& ComparableKey) const
873 {
875 CHECK_CONCURRENT_ACCESS(FPlatformAtomics::InterlockedIncrement(&ConcurrentReaders) >= 1);
876
878 IndexType BucketIndex = ModTableSize(HashValue.AsUInt());
879 const IndexType EndBucketIndex = ModTableSize(HashValue.AsUInt() + MaximumDistance + 1);
880 do
881 {
882 if (HashValue == HashData[BucketIndex])
883 {
884 if (Hasher::Matches(ComparableKey, KeyValueData.Get(IndexData[BucketIndex]).GetKey()))
885 {
886 CHECK_CONCURRENT_ACCESS(FPlatformAtomics::InterlockedDecrement(&ConcurrentReaders) >= 0);
888 return FHashElementId(IndexData[BucketIndex]);
889 }
890 }
891
892 BucketIndex = ModTableSize(BucketIndex + 1);
893 } while (BucketIndex != EndBucketIndex);
894
895 CHECK_CONCURRENT_ACCESS(FPlatformAtomics::InterlockedDecrement(&ConcurrentReaders) >= 0);
897
898 return FHashElementId();
899 }
900
901 inline FHashElementId FindId(const KeyType& Key) const
902 {
903 const FHashType HashValue = ComputeHash(Key);
904 return FindIdByHash(HashValue, Key);
905 }
906
907 FindValueType FindByHash(const FHashType HashValue, const KeyType& Key)
908 {
910 if (Id.IsValid())
911 {
912 return KeyValueData.Get(Id.GetIndex()).FindImpl();
913 }
914
915 return nullptr;
916 }
917
918 FindValueType Find(const KeyType& Key)
919 {
920 FHashElementId Id = FindId(Key);
921 if (Id.IsValid())
922 {
923 return KeyValueData.Get(Id.GetIndex()).FindImpl();
924 }
925
926 return nullptr;
927 }
928
929 const FindValueType FindByHash(const FHashType HashValue, const KeyType& Key) const
930 {
932 if (Id.IsValid())
933 {
934 return KeyValueData.Get(Id.GetIndex()).FindImpl();
935 }
936
937 return nullptr;
938 }
939
940 FindValueTypeConst Find(const KeyType& Key) const
941 {
942 FHashElementId Id = FindId(Key);
943 if (Id.IsValid())
944 {
945 return KeyValueData.Get(Id.GetIndex()).FindImpl();
946 }
947
948 return nullptr;
949 }
950
951 bool RemoveByHash(const FHashType HashValue, const KeyType& ComparableKey)
952 {
953 CHECK_CONCURRENT_ACCESS(FPlatformAtomics::InterlockedIncrement(&ConcurrentWriters) == 1);
954 CHECK_CONCURRENT_ACCESS(FPlatformAtomics::InterlockedIncrement(&ConcurrentReaders) == 1);
955
956 bool bIsFoundInMap = false;
958 IndexType BucketIndex = ModTableSize(HashValue.AsUInt());
959 const IndexType EndBucketIndex = ModTableSize(HashValue.AsUInt() + MaximumDistance + 1);
960 do
961 {
962 if (HashValue == HashData[BucketIndex])
963 {
964 if (Hasher::Matches(ComparableKey, KeyValueData.Get(IndexData[BucketIndex]).GetKey()))
965 {
966 KeyValueData.Deallocate(IndexData[BucketIndex]);
967 HashData[BucketIndex] = FHashType();
968 bIsFoundInMap = true;
969 break;
970 }
971 }
972
973 BucketIndex = ModTableSize(BucketIndex + 1);
974 } while (BucketIndex != EndBucketIndex);
975
976 if (bIsFoundInMap && (KeyValueData.Num() * LoadFactorQuotient * 4) < (SizePow2Minus1 * LoadFactorDivisor))
977 {
980 IndexType OldSizePow2Minus1 = SizePow2Minus1;
981 SizePow2Minus1 = SizePow2Minus1 / 2;
982 MaximumDistance = 0;
983 IndexData.Reserve(SizePow2Minus1 + 1);
984 IndexData.AddUninitialized(SizePow2Minus1 + 1);
985 HashData.Reserve(SizePow2Minus1 + 1);
986 HashData.AddDefaulted(SizePow2Minus1 + 1);
987
989 {
990 if (HashDataOld[Index].IsOccupied())
991 {
993 }
994 }
995 }
996
997 CHECK_CONCURRENT_ACCESS(FPlatformAtomics::InterlockedDecrement(&ConcurrentReaders) == 0);
998 CHECK_CONCURRENT_ACCESS(FPlatformAtomics::InterlockedDecrement(&ConcurrentWriters) == 0);
999
1000 return bIsFoundInMap;
1001 }
1002
1003 bool Remove(const KeyType& Key)
1004 {
1005 const FHashType HashValue = ComputeHash(Key);
1006 return RemoveByHash(HashValue, Key);
1007 }
1008
1010 {
1011 CHECK_CONCURRENT_ACCESS(FPlatformAtomics::InterlockedIncrement(&ConcurrentWriters) == 1);
1012 CHECK_CONCURRENT_ACCESS(FPlatformAtomics::InterlockedIncrement(&ConcurrentReaders) == 1);
1013
1014 bool bIsFoundInMap = false;
1015 FHashType HashValue = KeyValueData.Hashes[Id.GetIndex()];
1016 IndexType BucketIndex = ModTableSize(HashValue.AsUInt());
1017 const IndexType EndBucketIndex = ModTableSize(HashValue.AsUInt() + MaximumDistance + 1);
1018 do
1019 {
1020 if (Id.GetIndex() == IndexData[BucketIndex])
1021 {
1022 checkSlow(HashData[BucketIndex] == HashValue);
1023 KeyValueData.Deallocate(IndexData[BucketIndex]);
1024 HashData[BucketIndex] = FHashType();
1025 bIsFoundInMap = true;
1026 break;
1027 }
1028
1029 BucketIndex = ModTableSize(BucketIndex + 1);
1030 } while (BucketIndex != EndBucketIndex);
1031
1032 if (bIsFoundInMap && (KeyValueData.Num() * LoadFactorQuotient * 4) < (SizePow2Minus1 * LoadFactorDivisor))
1033 {
1036 IndexType OldSizePow2Minus1 = SizePow2Minus1;
1037 SizePow2Minus1 = SizePow2Minus1 / 2;
1038 MaximumDistance = 0;
1039 IndexData.Reserve(SizePow2Minus1 + 1);
1040 IndexData.AddUninitialized(SizePow2Minus1 + 1);
1041 HashData.Reserve(SizePow2Minus1 + 1);
1042 HashData.AddDefaulted(SizePow2Minus1 + 1);
1043
1045 {
1046 if (HashDataOld[Index].IsOccupied())
1047 {
1049 }
1050 }
1051 }
1052
1053 CHECK_CONCURRENT_ACCESS(FPlatformAtomics::InterlockedDecrement(&ConcurrentReaders) == 0);
1054 CHECK_CONCURRENT_ACCESS(FPlatformAtomics::InterlockedDecrement(&ConcurrentWriters) == 0);
1055
1056 return bIsFoundInMap;
1057 }
1058
1059 void Empty()
1060 {
1061 CHECK_CONCURRENT_ACCESS(FPlatformAtomics::InterlockedIncrement(&ConcurrentWriters) == 1);
1062 CHECK_CONCURRENT_ACCESS(FPlatformAtomics::InterlockedIncrement(&ConcurrentReaders) == 1);
1063
1064 IndexData.Empty(1);
1065 IndexData.AddUninitialized();
1066 HashData.Empty(1);
1067 HashData.AddDefaulted();
1068 KeyValueData.Empty();
1069 SizePow2Minus1 = 0;
1070 MaximumDistance = 0;
1071
1072 CHECK_CONCURRENT_ACCESS(FPlatformAtomics::InterlockedDecrement(&ConcurrentReaders) == 0);
1073 CHECK_CONCURRENT_ACCESS(FPlatformAtomics::InterlockedDecrement(&ConcurrentWriters) == 0);
1074 }
1075
1077 {
1078 CHECK_CONCURRENT_ACCESS(FPlatformAtomics::InterlockedIncrement(&ConcurrentWriters) == 1);
1079 CHECK_CONCURRENT_ACCESS(FPlatformAtomics::InterlockedIncrement(&ConcurrentReaders) == 1);
1080
1081 if (ReserveNum > KeyValueData.Num())
1082 {
1083 KeyValueData.Reserve(ReserveNum);
1084
1085 IndexType NewSizePow2Minus1 = SizePow2Minus1;
1087 {
1089 }
1090
1091 if (NewSizePow2Minus1 > SizePow2Minus1)
1092 {
1095 IndexType OldSizePow2Minus1 = SizePow2Minus1;
1096 SizePow2Minus1 = NewSizePow2Minus1;
1097 MaximumDistance = 0;
1098 IndexData.Reserve(SizePow2Minus1 + 1);
1099 IndexData.AddUninitialized(SizePow2Minus1 + 1);
1100 HashData.Reserve(SizePow2Minus1 + 1);
1101 HashData.AddDefaulted(SizePow2Minus1 + 1);
1102
1104 {
1105 if (HashDataOld[Index].IsOccupied())
1106 {
1108 }
1109 }
1110 }
1111 }
1112
1113 CHECK_CONCURRENT_ACCESS(FPlatformAtomics::InterlockedDecrement(&ConcurrentReaders) == 0);
1114 CHECK_CONCURRENT_ACCESS(FPlatformAtomics::InterlockedDecrement(&ConcurrentWriters) == 0);
1115 }
1116
1117 private:
1118 FData KeyValueData;
1119
1122
1123 IndexType SizePow2Minus1 = 0;
1124 IndexType MaximumDistance = 0;
1125
1126#if RUN_HASHTABLE_CONCURENCY_CHECKS
1127 mutable int ConcurrentReaders = 0;
1128 mutable int ConcurrentWriters = 0;
1129#endif
1130 };
1131}
1132
1133template<typename KeyType, typename ValueType, typename Hasher = TDefaultMapHashableKeyFuncs<KeyType, ValueType, false>, typename HashMapAllocator = FDefaultAllocator>
1134class TRobinHoodHashMap : public RobinHoodHashTable_Private::TRobinHoodHashTable<KeyType, ValueType, Hasher, HashMapAllocator>
1135{
1137 using IndexType = typename Base::IndexType;
1138 using FindValueType = typename Base::FindValueType;
1139 using FindValueTypeConst = typename Base::FindValueTypeConst;
1140
1141public:
1143 {
1144 static_assert(sizeof(Base) == sizeof(TRobinHoodHashMap), "This class should only limit the interface and not implement anything");
1145 }
1146
1151
1152 FHashElementId FindOrAddIdByHash(FHashType HashValue, const KeyType& Key, const ValueType& Val, bool& bIsAlreadyInMap)
1153 {
1154 return Base::FindOrAddIdByHash(HashValue, Key, Val, bIsAlreadyInMap);
1155 }
1156
1158 {
1159 return Base::FindOrAddIdByHash(HashValue, Key, MoveTemp(Val), bIsAlreadyInMap);
1160 }
1161
1163 {
1164 return Base::FindOrAddIdByHash(HashValue, MoveTemp(Key), Val, bIsAlreadyInMap);
1165 }
1166
1168 {
1169 return Base::FindOrAddIdByHash(HashValue, MoveTemp(Key), MoveTemp(Val), bIsAlreadyInMap);
1170 }
1171
1172 FHashElementId FindOrAddId(const KeyType& Key, const ValueType& Val, bool& bIsAlreadyInMap)
1173 {
1174 return Base::FindOrAddId(Key, Val, bIsAlreadyInMap);
1175 }
1176
1177 FHashElementId FindOrAddId(const KeyType& Key, ValueType&& Val, bool& bIsAlreadyInMap)
1178 {
1179 return Base::FindOrAddId(Key, MoveTemp(Val), bIsAlreadyInMap);
1180 }
1181
1182 FHashElementId FindOrAddId(KeyType&& Key, const ValueType& Val, bool& bIsAlreadyInMap)
1183 {
1184 return Base::FindOrAddId(MoveTemp(Key), Val);
1185 }
1186
1187 FHashElementId FindOrAddId(KeyType&& Key, ValueType&& Val, bool& bIsAlreadyInMap)
1188 {
1189 return Base::FindOrAddId(MoveTemp(Key), MoveTemp(Val), bIsAlreadyInMap);
1190 }
1191
1192 FindValueType FindOrAdd(const KeyType& Key, const ValueType& Val, bool& bIsAlreadyInMap)
1193 {
1194 return Base::FindOrAdd(Key, Val, bIsAlreadyInMap);
1195 }
1196
1197 FindValueType FindOrAdd(const KeyType& Key, ValueType&& Val, bool& bIsAlreadyInMap)
1198 {
1199 return Base::FindOrAdd(Key, MoveTemp(Val), bIsAlreadyInMap);
1200 }
1201
1202 FindValueType FindOrAdd(KeyType&& Key, const ValueType& Val, bool& bIsAlreadyInMap)
1203 {
1204 return Base::FindOrAdd(MoveTemp(Key), Val, bIsAlreadyInMap);
1205 }
1206
1207 FindValueType FindOrAdd(KeyType&& Key, ValueType&& Val, bool& bIsAlreadyInMap)
1208 {
1209 return Base::FindOrAdd(MoveTemp(Key), MoveTemp(Val), bIsAlreadyInMap);
1210 }
1211
1212 FHashElementId FindOrAddIdByHash(FHashType HashValue, const KeyType& Key, const ValueType& Val)
1213 {
1214 bool bIsAlreadyInMap;
1215 return Base::FindOrAddIdByHash(HashValue, Key, Val, bIsAlreadyInMap);
1216 }
1217
1218 FHashElementId FindOrAddIdByHash(FHashType HashValue, const KeyType& Key, ValueType&& Val)
1219 {
1220 bool bIsAlreadyInMap;
1221 return Base::FindOrAddIdByHash(HashValue, Key, MoveTemp(Val), bIsAlreadyInMap);
1222 }
1223
1224 FHashElementId FindOrAddIdByHash(FHashType HashValue, KeyType&& Key, const ValueType& Val)
1225 {
1226 bool bIsAlreadyInMap;
1227 return Base::FindOrAddIdByHash(HashValue, MoveTemp(Key), Val, bIsAlreadyInMap);
1228 }
1229
1231 {
1232 bool bIsAlreadyInMap;
1233 return Base::FindOrAddIdByHash(HashValue, MoveTemp(Key), MoveTemp(Val), bIsAlreadyInMap);
1234 }
1235
1236 FHashElementId FindOrAddId(const KeyType& Key, const ValueType& Val)
1237 {
1238 bool bIsAlreadyInMap;
1239 return Base::FindOrAddId(Key, Val, bIsAlreadyInMap);
1240 }
1241
1242 FHashElementId FindOrAddId(const KeyType& Key, ValueType&& Val)
1243 {
1244 bool bIsAlreadyInMap;
1245 return Base::FindOrAddId(Key, MoveTemp(Val), bIsAlreadyInMap);
1246 }
1247
1248 FHashElementId FindOrAddId(KeyType&& Key, const ValueType& Val)
1249 {
1250 bool bIsAlreadyInMap;
1251 return Base::FindOrAddId(MoveTemp(Key), Val);
1252 }
1253
1254 FHashElementId FindOrAddId(KeyType&& Key, ValueType&& Val)
1255 {
1256 bool bIsAlreadyInMap;
1257 return Base::FindOrAddId(MoveTemp(Key), MoveTemp(Val), bIsAlreadyInMap);
1258 }
1259
1260 FindValueType FindOrAdd(const KeyType& Key, const ValueType& Val)
1261 {
1262 bool bIsAlreadyInMap;
1263 return Base::FindOrAdd(Key, Val, bIsAlreadyInMap);
1264 }
1265
1266 FindValueType FindOrAdd(const KeyType& Key, ValueType&& Val)
1267 {
1268 bool bIsAlreadyInMap;
1269 return Base::FindOrAdd(Key, MoveTemp(Val), bIsAlreadyInMap);
1270 }
1271
1272 FindValueType FindOrAdd(KeyType&& Key, const ValueType& Val)
1273 {
1274 bool bIsAlreadyInMap;
1275 return Base::FindOrAdd(MoveTemp(Key), Val, bIsAlreadyInMap);
1276 }
1277
1278 FindValueType FindOrAdd(KeyType&& Key, ValueType&& Val)
1279 {
1280 bool bIsAlreadyInMap;
1281 return Base::FindOrAdd(MoveTemp(Key), MoveTemp(Val), bIsAlreadyInMap);
1282 }
1283
1284 FHashElementId UpdateIdByHash(FHashType HashValue, const KeyType& Key, const ValueType& Val, bool& bIsAlreadyInMap)
1285 {
1286 return Base::UpdateIdByHash(HashValue, Key, Val, bIsAlreadyInMap);
1287 }
1288
1289 FHashElementId UpdateIdByHash(FHashType HashValue, const KeyType& Key, ValueType&& Val, bool& bIsAlreadyInMap)
1290 {
1291 return Base::UpdateIdByHash(HashValue, Key, MoveTemp(Val), bIsAlreadyInMap);
1292 }
1293
1294 FHashElementId UpdateIdByHash(FHashType HashValue, KeyType&& Key, const ValueType& Val, bool& bIsAlreadyInMap)
1295 {
1296 return Base::UpdateIdByHash(HashValue, MoveTemp(Key), Val, bIsAlreadyInMap);
1297 }
1298
1300 {
1301 return Base::UpdateIdByHash(HashValue, MoveTemp(Key), MoveTemp(Val), bIsAlreadyInMap);
1302 }
1303
1304 FHashElementId UpdateId(const KeyType& Key, const ValueType& Val, bool& bIsAlreadyInMap)
1305 {
1306 return Base::UpdateId(Key, Val, bIsAlreadyInMap);
1307 }
1308
1309 FHashElementId UpdateId(const KeyType& Key, ValueType&& Val, bool& bIsAlreadyInMap)
1310 {
1311 return Base::UpdateId(Key, MoveTemp(Val), bIsAlreadyInMap);
1312 }
1313
1314 FHashElementId UpdateId(KeyType&& Key, const ValueType& Val, bool& bIsAlreadyInMap)
1315 {
1316 return Base::UpdateId(MoveTemp(Key), Val);
1317 }
1318
1319 FHashElementId UpdateId(KeyType&& Key, ValueType&& Val, bool& bIsAlreadyInMap)
1320 {
1321 return Base::UpdateId(MoveTemp(Key), MoveTemp(Val), bIsAlreadyInMap);
1322 }
1323
1324 FindValueType Update(const KeyType& Key, const ValueType& Val, bool& bIsAlreadyInMap)
1325 {
1326 return Base::Update(Key, Val, bIsAlreadyInMap);
1327 }
1328
1329 FindValueType Update(const KeyType& Key, ValueType&& Val, bool& bIsAlreadyInMap)
1330 {
1331 return Base::Update(Key, MoveTemp(Val), bIsAlreadyInMap);
1332 }
1333
1334 FindValueType Update(KeyType&& Key, const ValueType& Val, bool& bIsAlreadyInMap)
1335 {
1336 return Base::Update(MoveTemp(Key), Val, bIsAlreadyInMap);
1337 }
1338
1339 FindValueType Update(KeyType&& Key, ValueType&& Val, bool& bIsAlreadyInMap)
1340 {
1341 return Base::Update(MoveTemp(Key), MoveTemp(Val), bIsAlreadyInMap);
1342 }
1343
1344 FHashElementId UpdateIdByHash(FHashType HashValue, const KeyType& Key, const ValueType& Val)
1345 {
1346 bool bIsAlreadyInMap;
1347 return Base::UpdateIdByHash(HashValue, Key, Val, bIsAlreadyInMap);
1348 }
1349
1350 FHashElementId UpdateIdByHash(FHashType HashValue, const KeyType& Key, ValueType&& Val)
1351 {
1352 bool bIsAlreadyInMap;
1353 return Base::UpdateIdByHash(HashValue, Key, MoveTemp(Val), bIsAlreadyInMap);
1354 }
1355
1356 FHashElementId UpdateIdByHash(FHashType HashValue, KeyType&& Key, const ValueType& Val)
1357 {
1358 bool bIsAlreadyInMap;
1359 return Base::UpdateIdByHash(HashValue, MoveTemp(Key), Val, bIsAlreadyInMap);
1360 }
1361
1363 {
1364 bool bIsAlreadyInMap;
1365 return Base::UpdateIdByHash(HashValue, MoveTemp(Key), MoveTemp(Val), bIsAlreadyInMap);
1366 }
1367
1368 FHashElementId UpdateId(const KeyType& Key, const ValueType& Val)
1369 {
1370 bool bIsAlreadyInMap;
1371 return Base::UpdateId(Key, Val, bIsAlreadyInMap);
1372 }
1373
1374 FHashElementId UpdateId(const KeyType& Key, ValueType&& Val)
1375 {
1376 bool bIsAlreadyInMap;
1377 return Base::UpdateId(Key, MoveTemp(Val), bIsAlreadyInMap);
1378 }
1379
1380 FHashElementId UpdateId(KeyType&& Key, const ValueType& Val)
1381 {
1382 bool bIsAlreadyInMap;
1383 return Base::UpdateId(MoveTemp(Key), Val);
1384 }
1385
1386 FHashElementId UpdateId(KeyType&& Key, ValueType&& Val)
1387 {
1388 bool bIsAlreadyInMap;
1389 return Base::UpdateId(MoveTemp(Key), MoveTemp(Val), bIsAlreadyInMap);
1390 }
1391
1392 FindValueType Update(const KeyType& Key, const ValueType& Val)
1393 {
1394 bool bIsAlreadyInMap;
1395 return Base::Update(Key, Val, bIsAlreadyInMap);
1396 }
1397
1398 FindValueType Update(const KeyType& Key, ValueType&& Val)
1399 {
1400 bool bIsAlreadyInMap;
1401 return Base::Update(Key, MoveTemp(Val), bIsAlreadyInMap);
1402 }
1403
1404 FindValueType Update(KeyType&& Key, const ValueType& Val)
1405 {
1406 bool bIsAlreadyInMap;
1407 return Base::Update(MoveTemp(Key), Val, bIsAlreadyInMap);
1408 }
1409
1410 FindValueType Update(KeyType&& Key, ValueType&& Val)
1411 {
1412 bool bIsAlreadyInMap;
1413 return Base::Update(MoveTemp(Key), MoveTemp(Val), bIsAlreadyInMap);
1414 }
1415};
1416
1417template<typename KeyType, typename Hasher = DefaultKeyFuncs<KeyType, false>, typename HashMapAllocator = FDefaultAllocator>
1418class TRobinHoodHashSet : public RobinHoodHashTable_Private::TRobinHoodHashTable<KeyType, RobinHoodHashTable_Private::FUnitType, Hasher, HashMapAllocator>
1419{
1420 using Unit = RobinHoodHashTable_Private::FUnitType;
1422 using IndexType = typename Base::IndexType;
1423 using FindValueType = typename Base::FindValueType;
1424 using FindValueTypeConst = typename Base::FindValueTypeConst;
1425
1426public:
1428 {
1429 static_assert(sizeof(Base) == sizeof(TRobinHoodHashSet), "This class should only limit the interface and not implement anything");
1430 }
1431
1436
1438 {
1439 return Base::FindOrAddIdByHash(HashValue, Key, Unit(), bIsAlreadyInSet);
1440 }
1441
1443 {
1444 return Base::FindOrAddIdByHash(HashValue, MoveTemp(Key), Unit(), bIsAlreadyInSet);
1445 }
1446
1447 FHashElementId FindOrAddId(const KeyType& Key, bool& bIsAlreadyInSet)
1448 {
1449 return Base::FindOrAddId(Key, Unit(), bIsAlreadyInSet);
1450 }
1451
1453 {
1454 return Base::FindOrAddId(MoveTemp(Key), Unit(), bIsAlreadyInSet);
1455 }
1456
1457 FindValueType FindOrAdd(const KeyType& Key, bool& bIsAlreadyInSet)
1458 {
1459 return Base::FindOrAdd(Key, Unit(), bIsAlreadyInSet);
1460 }
1461
1462 FindValueType FindOrAdd(KeyType&& Key, bool& bIsAlreadyInSet)
1463 {
1464 return Base::FindOrAdd(MoveTemp(Key), Unit(), bIsAlreadyInSet);
1465 }
1466
1468 {
1469 bool bIsAlreadyInSet;
1470 return Base::FindOrAddIdByHash(HashValue, Key, Unit(), bIsAlreadyInSet);
1471 }
1472
1474 {
1475 bool bIsAlreadyInSet;
1476 return Base::FindOrAddIdByHash(HashValue, MoveTemp(Key), Unit(), bIsAlreadyInSet);
1477 }
1478
1479 FHashElementId FindOrAddId(const KeyType& Key)
1480 {
1481 bool bIsAlreadyInSet;
1482 return Base::FindOrAddId(Key, Unit(), bIsAlreadyInSet);
1483 }
1484
1486 {
1487 bool bIsAlreadyInSet;
1488 return Base::FindOrAddId(MoveTemp(Key), Unit(), bIsAlreadyInSet);
1489 }
1490
1491 FindValueType FindOrAdd(const KeyType& Key)
1492 {
1493 bool bIsAlreadyInSet;
1494 return Base::FindOrAdd(Key, Unit(), bIsAlreadyInSet);
1495 }
1496
1497 FindValueType FindOrAdd(KeyType&& Key)
1498 {
1499 bool bIsAlreadyInSet;
1500 return Base::FindOrAdd(MoveTemp(Key), Unit(), bIsAlreadyInSet);
1501 }
1502};
1503
1504};
1505
1506#undef CHECK_CONCURRENT_ACCESS
1507#undef RUN_HASHTABLE_CONCURENCY_CHECKS
#define checkSlow(expr)
Definition AssertionMacros.h:332
@ INDEX_NONE
Definition CoreMiscDefines.h:150
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
@ Num
Definition MetalRHIPrivate.h:234
#define CHECK_CONCURRENT_ACCESS(x)
Definition RobinHoodHashTable.h:14
float Val(const FString &Value)
Definition UnrealMath.cpp:3163
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 RobinHoodHashTable.h:72
FHashElementId()
Definition RobinHoodHashTable.h:74
FHashElementId(int32 InIndex)
Definition RobinHoodHashTable.h:75
bool IsValid() const
Definition RobinHoodHashTable.h:82
bool operator==(FHashElementId InHashElementId) const
Definition RobinHoodHashTable.h:87
int32 GetIndex() const
Definition RobinHoodHashTable.h:77
Definition RobinHoodHashTable.h:27
FHashType()
Definition RobinHoodHashTable.h:29
uint32 IntType
Definition RobinHoodHashTable.h:41
IntType AsUInt() const
Definition RobinHoodHashTable.h:43
bool operator!=(FHashType Other) const
Definition RobinHoodHashTable.h:36
bool operator==(FHashType Other) const
Definition RobinHoodHashTable.h:31
FConstIteratorType & operator++()
Definition RobinHoodHashTable.h:820
const ElementType & operator*() const
Definition RobinHoodHashTable.h:815
FHashElementId GetElementId() const
Definition RobinHoodHashTable.h:826
bool operator!=(const FConstIteratorType &Rhs) const
Definition RobinHoodHashTable.h:810
bool operator==(const FConstIteratorType &Rhs) const
Definition RobinHoodHashTable.h:805
bool operator!=(const FIteratorType &Rhs) const
Definition RobinHoodHashTable.h:752
FIteratorType & operator++()
Definition RobinHoodHashTable.h:762
bool operator==(const FIteratorType &Rhs) const
Definition RobinHoodHashTable.h:747
ElementType & operator*() const
Definition RobinHoodHashTable.h:757
FHashElementId GetElementId() const
Definition RobinHoodHashTable.h:768
FindValueType Find(const KeyType &Key)
Definition RobinHoodHashTable.h:918
typename KeyValueType::FindValueType FindValueType
Definition RobinHoodHashTable.h:320
SIZE_T SizeType
Definition RobinHoodHashTable.h:324
FindValueType FindByHash(const FHashType HashValue, const KeyType &Key)
Definition RobinHoodHashTable.h:907
typename KeyValueType::ElementType ElementType
Definition RobinHoodHashTable.h:322
FIteratorType begin()
Definition RobinHoodHashTable.h:774
int32 Num() const
Definition RobinHoodHashTable.h:847
FHashElementId UpdateId(DeducedKeyType &&Key, DeducedValueType &&Val, bool &bIsAlreadyInMap)
Definition RobinHoodHashTable.h:629
TRobinHoodHashTable()
Definition RobinHoodHashTable.h:642
SizeType GetAllocatedSize() const
Definition RobinHoodHashTable.h:842
FIteratorType end()
Definition RobinHoodHashTable.h:779
FindValueTypeConst Find(const KeyType &Key) const
Definition RobinHoodHashTable.h:940
FHashElementId FindIdByHash(const FHashType HashValue, const KeyType &ComparableKey) const
Definition RobinHoodHashTable.h:872
bool RemoveByElementId(FHashElementId Id)
Definition RobinHoodHashTable.h:1009
FHashElementId FindId(const KeyType &Key) const
Definition RobinHoodHashTable.h:901
FHashElementId FindOrAddIdByHash(FHashType HashValue, DeducedKeyType &&Key, DeducedValueType &&Val, bool &bIsAlreadyInMap)
Definition RobinHoodHashTable.h:603
void InsertIntoTable(IndexType Index, FHashType Hash)
Definition RobinHoodHashTable.h:495
typename KeyValueType::FindValueTypeConst FindValueTypeConst
Definition RobinHoodHashTable.h:321
static constexpr const IndexType InvalidIndex
Definition RobinHoodHashTable.h:328
void Reserve(SizeType ReserveNum)
Definition RobinHoodHashTable.h:1076
TRobinHoodHashTable(TRobinHoodHashTable &&Other)
Definition RobinHoodHashTable.h:689
FConstIteratorType begin() const
Definition RobinHoodHashTable.h:832
const FindValueType FindByHash(const FHashType HashValue, const KeyType &Key) const
Definition RobinHoodHashTable.h:929
IndexType GetMaxIndex() const
Definition RobinHoodHashTable.h:852
FHashElementId FindOrAddId(DeducedKeyType &&Key, DeducedValueType &&Val, bool &bIsAlreadyInMap)
Definition RobinHoodHashTable.h:609
bool RemoveByHash(const FHashType HashValue, const KeyType &ComparableKey)
Definition RobinHoodHashTable.h:951
uint32 IndexType
Definition RobinHoodHashTable.h:323
void Empty()
Definition RobinHoodHashTable.h:1059
bool Remove(const KeyType &Key)
Definition RobinHoodHashTable.h:1003
IndexType ModTableSize(IndexType HashValue) const
Definition RobinHoodHashTable.h:490
static constexpr const IndexType LoadFactorQuotient
Definition RobinHoodHashTable.h:327
bool ContainsElementId(FHashElementId Id) const
Definition RobinHoodHashTable.h:867
ElementType & GetByElementId(FHashElementId Id)
Definition RobinHoodHashTable.h:857
RobinHoodHashTable_Private::TKeyValue< KeyType, ValueType > KeyValueType
Definition RobinHoodHashTable.h:319
TRobinHoodHashTable & operator=(const TRobinHoodHashTable &Other)
Definition RobinHoodHashTable.h:666
FHashElementId UpdateIdByHash(FHashType HashValue, DeducedKeyType &&Key, DeducedValueType &&Val, bool &bIsAlreadyInMap)
Definition RobinHoodHashTable.h:623
static FHashType ComputeHash(const KeyType &Key)
Definition RobinHoodHashTable.h:719
FindValueType Update(DeducedKeyType &&Key, DeducedValueType &&Val, bool &bIsAlreadyInMap)
Definition RobinHoodHashTable.h:636
FConstIteratorType end() const
Definition RobinHoodHashTable.h:837
const ElementType & GetByElementId(FHashElementId Id) const
Definition RobinHoodHashTable.h:862
TRobinHoodHashTable(const TRobinHoodHashTable &Other)
Definition RobinHoodHashTable.h:648
FindValueType FindOrAdd(DeducedKeyType &&Key, DeducedValueType &&Val, bool &bIsAlreadyInMap)
Definition RobinHoodHashTable.h:616
TRobinHoodHashTable & operator=(TRobinHoodHashTable &&Other)
Definition RobinHoodHashTable.h:701
static constexpr const IndexType LoadFactorDivisor
Definition RobinHoodHashTable.h:326
Definition RobinHoodHashTable.h:1135
FindValueType Update(KeyType &&Key, const ValueType &Val)
Definition RobinHoodHashTable.h:1404
FHashElementId UpdateId(KeyType &&Key, ValueType &&Val)
Definition RobinHoodHashTable.h:1386
FHashElementId UpdateId(KeyType &&Key, ValueType &&Val, bool &bIsAlreadyInMap)
Definition RobinHoodHashTable.h:1319
TRobinHoodHashMap & operator=(TRobinHoodHashMap &&Other)=default
FHashElementId UpdateIdByHash(FHashType HashValue, KeyType &&Key, const ValueType &Val, bool &bIsAlreadyInMap)
Definition RobinHoodHashTable.h:1294
FindValueType FindOrAdd(const KeyType &Key, ValueType &&Val, bool &bIsAlreadyInMap)
Definition RobinHoodHashTable.h:1197
TRobinHoodHashMap()
Definition RobinHoodHashTable.h:1142
FHashElementId UpdateIdByHash(FHashType HashValue, const KeyType &Key, ValueType &&Val, bool &bIsAlreadyInMap)
Definition RobinHoodHashTable.h:1289
FHashElementId FindOrAddId(const KeyType &Key, ValueType &&Val, bool &bIsAlreadyInMap)
Definition RobinHoodHashTable.h:1177
FHashElementId UpdateId(const KeyType &Key, ValueType &&Val, bool &bIsAlreadyInMap)
Definition RobinHoodHashTable.h:1309
FHashElementId FindOrAddId(KeyType &&Key, ValueType &&Val, bool &bIsAlreadyInMap)
Definition RobinHoodHashTable.h:1187
FHashElementId FindOrAddIdByHash(FHashType HashValue, const KeyType &Key, ValueType &&Val)
Definition RobinHoodHashTable.h:1218
FHashElementId UpdateId(const KeyType &Key, ValueType &&Val)
Definition RobinHoodHashTable.h:1374
FHashElementId FindOrAddId(KeyType &&Key, const ValueType &Val)
Definition RobinHoodHashTable.h:1248
FHashElementId FindOrAddId(KeyType &&Key, const ValueType &Val, bool &bIsAlreadyInMap)
Definition RobinHoodHashTable.h:1182
FindValueType FindOrAdd(KeyType &&Key, ValueType &&Val, bool &bIsAlreadyInMap)
Definition RobinHoodHashTable.h:1207
FindValueType Update(const KeyType &Key, ValueType &&Val)
Definition RobinHoodHashTable.h:1398
FHashElementId FindOrAddIdByHash(FHashType HashValue, KeyType &&Key, ValueType &&Val)
Definition RobinHoodHashTable.h:1230
FHashElementId FindOrAddId(const KeyType &Key, const ValueType &Val, bool &bIsAlreadyInMap)
Definition RobinHoodHashTable.h:1172
FindValueType Update(KeyType &&Key, ValueType &&Val, bool &bIsAlreadyInMap)
Definition RobinHoodHashTable.h:1339
TRobinHoodHashMap & operator=(const TRobinHoodHashMap &Other)=default
FHashElementId UpdateIdByHash(FHashType HashValue, KeyType &&Key, ValueType &&Val, bool &bIsAlreadyInMap)
Definition RobinHoodHashTable.h:1299
FHashElementId FindOrAddIdByHash(FHashType HashValue, KeyType &&Key, ValueType &&Val, bool &bIsAlreadyInMap)
Definition RobinHoodHashTable.h:1167
FindValueType FindOrAdd(const KeyType &Key, const ValueType &Val, bool &bIsAlreadyInMap)
Definition RobinHoodHashTable.h:1192
FHashElementId UpdateIdByHash(FHashType HashValue, KeyType &&Key, const ValueType &Val)
Definition RobinHoodHashTable.h:1356
FHashElementId FindOrAddId(const KeyType &Key, const ValueType &Val)
Definition RobinHoodHashTable.h:1236
FHashElementId UpdateId(const KeyType &Key, const ValueType &Val)
Definition RobinHoodHashTable.h:1368
FHashElementId UpdateId(const KeyType &Key, const ValueType &Val, bool &bIsAlreadyInMap)
Definition RobinHoodHashTable.h:1304
FindValueType FindOrAdd(KeyType &&Key, const ValueType &Val)
Definition RobinHoodHashTable.h:1272
FHashElementId FindOrAddIdByHash(FHashType HashValue, KeyType &&Key, const ValueType &Val)
Definition RobinHoodHashTable.h:1224
FindValueType Update(KeyType &&Key, const ValueType &Val, bool &bIsAlreadyInMap)
Definition RobinHoodHashTable.h:1334
TRobinHoodHashMap(const TRobinHoodHashMap &Other)=default
FHashElementId FindOrAddIdByHash(FHashType HashValue, const KeyType &Key, const ValueType &Val, bool &bIsAlreadyInMap)
Definition RobinHoodHashTable.h:1152
FHashElementId UpdateId(KeyType &&Key, const ValueType &Val, bool &bIsAlreadyInMap)
Definition RobinHoodHashTable.h:1314
FHashElementId FindOrAddId(KeyType &&Key, ValueType &&Val)
Definition RobinHoodHashTable.h:1254
FHashElementId UpdateIdByHash(FHashType HashValue, KeyType &&Key, ValueType &&Val)
Definition RobinHoodHashTable.h:1362
FHashElementId FindOrAddIdByHash(FHashType HashValue, const KeyType &Key, const ValueType &Val)
Definition RobinHoodHashTable.h:1212
FHashElementId FindOrAddIdByHash(FHashType HashValue, const KeyType &Key, ValueType &&Val, bool &bIsAlreadyInMap)
Definition RobinHoodHashTable.h:1157
FindValueType Update(KeyType &&Key, ValueType &&Val)
Definition RobinHoodHashTable.h:1410
FindValueType FindOrAdd(const KeyType &Key, ValueType &&Val)
Definition RobinHoodHashTable.h:1266
FHashElementId FindOrAddId(const KeyType &Key, ValueType &&Val)
Definition RobinHoodHashTable.h:1242
FindValueType Update(const KeyType &Key, const ValueType &Val, bool &bIsAlreadyInMap)
Definition RobinHoodHashTable.h:1324
FHashElementId UpdateId(KeyType &&Key, const ValueType &Val)
Definition RobinHoodHashTable.h:1380
FindValueType Update(const KeyType &Key, ValueType &&Val, bool &bIsAlreadyInMap)
Definition RobinHoodHashTable.h:1329
FindValueType Update(const KeyType &Key, const ValueType &Val)
Definition RobinHoodHashTable.h:1392
FHashElementId UpdateIdByHash(FHashType HashValue, const KeyType &Key, ValueType &&Val)
Definition RobinHoodHashTable.h:1350
FindValueType FindOrAdd(const KeyType &Key, const ValueType &Val)
Definition RobinHoodHashTable.h:1260
FHashElementId FindOrAddIdByHash(FHashType HashValue, KeyType &&Key, const ValueType &Val, bool &bIsAlreadyInMap)
Definition RobinHoodHashTable.h:1162
FHashElementId UpdateIdByHash(FHashType HashValue, const KeyType &Key, const ValueType &Val, bool &bIsAlreadyInMap)
Definition RobinHoodHashTable.h:1284
FindValueType FindOrAdd(KeyType &&Key, ValueType &&Val)
Definition RobinHoodHashTable.h:1278
FindValueType FindOrAdd(KeyType &&Key, const ValueType &Val, bool &bIsAlreadyInMap)
Definition RobinHoodHashTable.h:1202
FHashElementId UpdateIdByHash(FHashType HashValue, const KeyType &Key, const ValueType &Val)
Definition RobinHoodHashTable.h:1344
TRobinHoodHashMap(TRobinHoodHashMap &&Other)=default
Definition RobinHoodHashTable.h:1419
TRobinHoodHashSet()
Definition RobinHoodHashTable.h:1427
FindValueType FindOrAdd(const KeyType &Key)
Definition RobinHoodHashTable.h:1491
FHashElementId FindOrAddId(const KeyType &Key, bool &bIsAlreadyInSet)
Definition RobinHoodHashTable.h:1447
FindValueType FindOrAdd(KeyType &&Key)
Definition RobinHoodHashTable.h:1497
TRobinHoodHashSet & operator=(TRobinHoodHashSet &&Other)=default
FHashElementId FindOrAddIdByHash(FHashType HashValue, const KeyType &Key)
Definition RobinHoodHashTable.h:1467
FHashElementId FindOrAddId(const KeyType &Key)
Definition RobinHoodHashTable.h:1479
FHashElementId FindOrAddIdByHash(FHashType HashValue, KeyType &&Key, bool &bIsAlreadyInSet)
Definition RobinHoodHashTable.h:1442
TRobinHoodHashSet(TRobinHoodHashSet &&Other)=default
FindValueType FindOrAdd(KeyType &&Key, bool &bIsAlreadyInSet)
Definition RobinHoodHashTable.h:1462
FindValueType FindOrAdd(const KeyType &Key, bool &bIsAlreadyInSet)
Definition RobinHoodHashTable.h:1457
TRobinHoodHashSet & operator=(const TRobinHoodHashSet &Other)=default
FHashElementId FindOrAddId(KeyType &&Key, bool &bIsAlreadyInSet)
Definition RobinHoodHashTable.h:1452
TRobinHoodHashSet(const TRobinHoodHashSet &Other)=default
FHashElementId FindOrAddIdByHash(FHashType HashValue, KeyType &&Key)
Definition RobinHoodHashTable.h:1473
FHashElementId FindOrAddId(KeyType &&Key)
Definition RobinHoodHashTable.h:1485
FHashElementId FindOrAddIdByHash(FHashType HashValue, const KeyType &Key, bool &bIsAlreadyInSet)
Definition RobinHoodHashTable.h:1437
Definition Array.h:670
UE_REWRITE SizeType Num() const
Definition Array.h:1144
UE_NODEBUG UE_FORCEINLINE_HINT ElementType & Last(SizeType IndexFromTheEnd=0) UE_LIFETIMEBOUND
Definition Array.h:1263
void RemoveAt(SizeType Index, EAllowShrinking AllowShrinking=UE::Core::Private::AllowShrinkingByDefault< AllocatorType >())
Definition Array.h:2083
UE_NODEBUG UE_FORCEINLINE_HINT void Push(ElementType &&Item)
Definition Array.h:1224
void Reset(SizeType NewSize=0)
Definition Array.h:2246
void SetNumUnsafeInternal(SizeType NewNum)
Definition Array.h:2395
UE_NODEBUG UE_FORCEINLINE_HINT SIZE_T GetAllocatedSize(void) const
Definition Array.h:1059
ElementType Pop(EAllowShrinking AllowShrinking=UE::Core::Private::AllowShrinkingByDefault< AllocatorType >())
Definition Array.h:1196
SizeType Insert(std::initializer_list< ElementType > InitList, const SizeType InIndex)
Definition Array.h:1875
void Empty(SizeType Slack=0)
Definition Array.h:2273
UE_FORCEINLINE_HINT void Reserve(SizeType Number)
Definition Array.h:3016
Definition ContainerAllocationPolicies.h:894
@ Contains
Definition AutomationTest.h:160
Definition RobinHoodHashTable.h:18
SIZE_T GetAllocatedSize(const T &Value)
Definition ManagedArray.h:93
void GetElement(const UTypedElementRegistry *InRegistry, const HandleType &InElementHandle, TTypedElement< BaseInterfaceType > &OutElement)
Definition TypedElementList.h:39
EValueType FindValueType(FName Name)
Definition ShaderValue.cpp:630
U16 Index
Definition radfft.cpp:71
bool operator==(const FIteratorState &Rhs) const
Definition RobinHoodHashTable.h:428
bool operator!=(const FIteratorState &Rhs) const
Definition RobinHoodHashTable.h:433
void Reserve(SizeType ReserveNum)
Definition RobinHoodHashTable.h:476
void Deallocate(IndexType Index)
Definition RobinHoodHashTable.h:370
FIteratorState Next(FIteratorState State) const
Definition RobinHoodHashTable.h:439
bool Contains(IndexType Index) const
Definition RobinHoodHashTable.h:389
IndexType Allocate(DeducedKeyType &&Key, DeducedValueType &&Val, FHashType Hash)
Definition RobinHoodHashTable.h:346
IndexType GetMaxIndex() const
Definition RobinHoodHashTable.h:419
TFreeList< InlineOneAllocatorType > FreeList
Definition RobinHoodHashTable.h:487
FIteratorState Start() const
Definition RobinHoodHashTable.h:451
KeyValueType & Get(IndexType Index)
Definition RobinHoodHashTable.h:404
TArray< KeyValueType, HashMapAllocator > KeyVals
Definition RobinHoodHashTable.h:485
SizeType GetAllocatedSize() const
Definition RobinHoodHashTable.h:340
const KeyValueType & Get(IndexType Index) const
Definition RobinHoodHashTable.h:394
TArray< FHashType, HashMapAllocator > Hashes
Definition RobinHoodHashTable.h:486
SizeType Num() const
Definition RobinHoodHashTable.h:414
FIteratorState End() const
Definition RobinHoodHashTable.h:456
Definition Tuple.h:652