14template <
class Key,
class KeyValue,
class HashTableDetail,
class Hash,
class KeyEqual>
25 template <
class Table,
class Iterator>
32 using iterator_category = std::forward_iterator_tag;
35 IteratorBase(
const IteratorBase &inRHS) =
default;
38 IteratorBase & operator = (
const IteratorBase &inRHS) =
default;
41 explicit IteratorBase(Table *inTable) :
45 while (mIndex < mTable->mMaxSize && (mTable->mControl[mIndex] & cBucketUsed) == 0)
50 IteratorBase(Table *inTable,
size_type inIndex) :
57 Iterator & operator ++ ()
65 while (mIndex < mTable->mMaxSize && (mTable->mControl[mIndex] & cBucketUsed) == 0);
67 return static_cast<Iterator &
>(*this);
71 Iterator operator ++ (
int)
73 Iterator result(mTable, mIndex);
79 const KeyValue & operator * ()
const
82 return mTable->mData[mIndex];
86 const KeyValue * operator -> ()
const
89 return mTable->mData + mIndex;
93 bool operator == (
const Iterator &inRHS)
const
95 return mIndex == inRHS.mIndex && mTable == inRHS.mTable;
99 bool operator != (
const Iterator &inRHS)
const
101 return !(*
this == inRHS);
107 return mIndex < mTable->mMaxSize
108 && (mTable->mControl[mIndex] & cBucketUsed) != 0;
120 mMaxSize = inMaxSize;
121 mMaxLoad =
uint32((cMaxLoadFactorNumerator * inMaxSize) / cMaxLoadFactorDenominator);
122 size_type required_size = mMaxSize * (
sizeof(KeyValue) + 1) + 15;
123 if constexpr (cNeedsAlignedAllocate)
124 mData =
reinterpret_cast<KeyValue *
>(
AlignedAllocate(required_size,
alignof(KeyValue)));
126 mData =
reinterpret_cast<KeyValue *
>(
Allocate(required_size));
127 mControl =
reinterpret_cast<uint8 *
>(mData + mMaxSize);
136 AllocateTable(inRHS.mMaxSize);
139 memcpy(mControl, inRHS.mControl, mMaxSize + 15);
143 for (
const uint8 *control = mControl, *control_end = mControl + mMaxSize; control != control_end; ++control, ++index)
144 if (*control & cBucketUsed)
145 ::new (mData + index) KeyValue(inRHS.mData[index]);
153 size_type new_max_size = max<size_type>(mMaxSize << 1, 16);
154 if (new_max_size < mMaxSize)
156 JPH_ASSERT(
false,
"Overflow in hash table size, can't grow!");
162 KeyValue *old_data = mData;
163 const uint8 *old_control = mControl;
171 AllocateTable(new_max_size);
174 memset(mControl, cBucketEmpty, mMaxSize + 15);
176 if (old_data !=
nullptr)
179 for (
size_type i = 0; i < old_max_size; ++i)
180 if (old_control[i] & cBucketUsed)
183 KeyValue *element = old_data + i;
186 ::new (mData + index) KeyValue(
std::move(*element));
187 element->~KeyValue();
191 if constexpr (cNeedsAlignedAllocate)
202 return mData[inIndex];
207 template <
bool AllowDeleted = true>
211 if (mSize + 1 >= mMaxLoad)
218 uint8 control = cBucketUsed |
uint8(hash_value);
228 size_type first_deleted_index = cNoDeleted;
244 if constexpr (AllowDeleted)
245 if (first_deleted_index == cNoDeleted)
249 if (control_deleted != 0)
257 while ((control_equal | control_empty) != 0)
264 if (first_equal < first_empty)
267 local_index += first_equal;
270 local_index &= bucket_mask;
273 if (equal(HashTableDetail::sGetKey(mData[local_index]), inKey))
276 outIndex = local_index;
282 uint shift = first_equal + 1;
283 control_equal >>= shift;
284 control_empty >>= shift;
292 local_index += first_empty;
293 if constexpr (AllowDeleted)
294 if (first_deleted_index < local_index)
295 local_index = first_deleted_index;
298 local_index &= bucket_mask;
301 mControl[local_index] = control;
302 if (local_index < 15)
303 mControl[mMaxSize + local_index] = control;
307 outIndex = local_index;
313 index = (index + 16) & bucket_mask;
319 class iterator :
public IteratorBase<HashTable, iterator>
321 using Base = IteratorBase<HashTable, iterator>;
336 using Base::operator *;
342 return this->mTable->mData[this->mIndex];
345 using Base::operator ->;
351 return this->mTable->mData + this->mIndex;
358 using Base = IteratorBase<const HashTable, const_iterator>;
363 using pointer =
const typename Base::value_type *;
388 mControl(ioRHS.mControl),
390 mMaxSize(ioRHS.mMaxSize),
391 mMaxLoad(ioRHS.mMaxLoad)
393 ioRHS.mData =
nullptr;
394 ioRHS.mControl =
nullptr;
423 size_type max_size =
GetNextPowerOf2(max<uint32>((cMaxLoadFactorDenominator * inMaxSize) / cMaxLoadFactorNumerator, 16));
424 if (max_size <= mMaxSize)
428 AllocateTable(max_size);
431 memset(mControl, cBucketEmpty, mMaxSize + 15);
438 if constexpr (!std::is_trivially_destructible<KeyValue>())
441 if (mControl[i] & cBucketUsed)
442 mData[i].~KeyValue();
444 if (mData !=
nullptr)
447 if constexpr (cNeedsAlignedAllocate)
513 bool inserted =
InsertKey(HashTableDetail::sGetKey(inValue), index);
515 ::new (mData + index) KeyValue(inValue);
516 return std::make_pair(
iterator(
this, index), inserted);
530 uint8 control = cBucketUsed |
uint8(hash_value);
554 while ((control_equal | control_empty) != 0)
561 if (first_equal < first_empty)
564 local_index += first_equal;
567 local_index &= bucket_mask;
570 if (equal(HashTableDetail::sGetKey(mData[local_index]), inKey))
578 uint shift = first_equal + 1;
579 control_equal >>= shift;
580 control_empty >>= shift;
591 index = (index + 16) & bucket_mask;
601 mControl[inIterator.mIndex] = cBucketDeleted;
602 if (inIterator.mIndex < 15)
603 mControl[inIterator.mIndex + mMaxSize] = cBucketDeleted;
606 mData[inIterator.mIndex].~KeyValue();
626 std::swap(mData, ioRHS.mData);
627 std::swap(mControl, ioRHS.mControl);
628 std::swap(mSize, ioRHS.mSize);
629 std::swap(mMaxSize, ioRHS.mMaxSize);
630 std::swap(mMaxLoad, ioRHS.mMaxLoad);
635 static constexpr bool cNeedsAlignedAllocate =
alignof(KeyValue) > (JPH_CPU_ADDRESS_BITS == 32? 8 : 16);
638 static constexpr uint64 cMaxLoadFactorNumerator = 7;
639 static constexpr uint64 cMaxLoadFactorDenominator = 8;
642 static constexpr uint8 cBucketEmpty = 0;
643 static constexpr uint8 cBucketDeleted = 0x7f;
644 static constexpr uint8 cBucketUsed = 0x80;
647 KeyValue * mData =
nullptr;
650 uint8 * mControl =
nullptr;
std::uint8_t uint8
Definition Core.h:447
std::uint64_t uint64
Definition Core.h:450
unsigned int uint
Definition Core.h:446
#define JPH_NAMESPACE_END
Definition Core.h:379
std::uint32_t uint32
Definition Core.h:449
#define JPH_NAMESPACE_BEGIN
Definition Core.h:373
#define JPH_IF_ENABLE_ASSERTS(...)
Definition IssueReporting.h:35
#define JPH_ASSERT(...)
Definition IssueReporting.h:33
uint CountTrailingZeros(uint32 inValue)
Compute number of trailing zero bits (how many low bits are zero)
Definition Math.h:95
uint32 GetNextPowerOf2(uint32 inValue)
Get the next higher power of 2 of a value, or the value itself if the value is already a power of 2.
Definition Math.h:182
AllocateFunction Allocate
Definition Memory.cpp:68
FreeFunction Free
Definition Memory.cpp:70
AlignedFreeFunction AlignedFree
Definition Memory.cpp:72
AlignedAllocateFunction AlignedAllocate
Definition Memory.cpp:71
A vector consisting of 16 bytes.
Definition BVec16.h:11
static JPH_INLINE BVec16 sZero()
Vector with all zeros.
Definition BVec16.inl:46
static JPH_INLINE BVec16 sEquals(BVec16Arg inV1, BVec16Arg inV2)
Equals (component wise), highest bit of each component that is set is considered true.
Definition BVec16.inl:83
static JPH_INLINE BVec16 sReplicate(uint8 inV)
Replicate int inV across all components.
Definition BVec16.inl:57
static JPH_INLINE BVec16 sLoadByte16(const uint8 *inV)
Load 16 bytes from memory.
Definition BVec16.inl:72
Const iterator.
Definition HashTable.h:357
const_iterator(const HashTable *inTable, size_type inIndex)
Definition HashTable.h:367
const_iterator & operator=(const iterator &inRHS)
Assignment.
Definition HashTable.h:372
const typename Base::value_type * pointer
Definition HashTable.h:363
const_iterator(const iterator &inIterator)
Definition HashTable.h:369
const_iterator(const HashTable *inTable)
Constructors.
Definition HashTable.h:366
const typename Base::value_type & reference
Properties.
Definition HashTable.h:362
const_iterator(const const_iterator &inRHS)
Definition HashTable.h:368
Non-const iterator.
Definition HashTable.h:320
typename Base::value_type * pointer
Definition HashTable.h:326
typename Base::value_type & reference
Properties.
Definition HashTable.h:325
KeyValue & operator*()
Non-const access to key value pair.
Definition HashTable.h:339
KeyValue * operator->()
Non-const access to key value pair.
Definition HashTable.h:348
iterator(HashTable *inTable)
Constructors.
Definition HashTable.h:329
iterator & operator=(const iterator &inRHS)
Assignment.
Definition HashTable.h:334
iterator(HashTable *inTable, size_type inIndex)
Definition HashTable.h:330
iterator(const iterator &inIterator)
Definition HashTable.h:331
Definition HashTable.h:16
void reserve(size_type inMaxSize)
Reserve memory for a certain number of elements.
Definition HashTable.h:420
ptrdiff_t difference_type
Definition HashTable.h:21
void clear()
Destroy the entire hash table.
Definition HashTable.h:435
KeyValue & GetElement(size_type inIndex) const
Get an element by index.
Definition HashTable.h:200
iterator end()
Iterator to one beyond last element.
Definition HashTable.h:468
HashTable(const HashTable &inRHS)
Copy constructor.
Definition HashTable.h:380
size_type size() const
Number of elements in the table.
Definition HashTable.h:504
HashTable()=default
Default constructor.
void swap(HashTable &ioRHS) noexcept
Swap the contents of two hash tables.
Definition HashTable.h:624
const_iterator cbegin() const
Iterator to first element.
Definition HashTable.h:486
~HashTable()
Destructor.
Definition HashTable.h:414
iterator begin()
Iterator to first element.
Definition HashTable.h:462
const_iterator end() const
Iterator to one beyond last element.
Definition HashTable.h:480
const_iterator find(const Key &inKey) const
Find an element, returns iterator to element or end() if not found.
Definition HashTable.h:520
const_iterator cend() const
Iterator to one beyond last element.
Definition HashTable.h:492
HashTable(HashTable &&ioRHS) noexcept
Move constructor.
Definition HashTable.h:386
KeyValue value_type
Properties.
Definition HashTable.h:19
bool InsertKey(const Key &inKey, size_type &outIndex)
Definition HashTable.h:208
uint32 size_type
Definition HashTable.h:20
bool empty() const
Check if there are no elements in the table.
Definition HashTable.h:498
std::pair< iterator, bool > insert(const value_type &inValue)
Insert a new element, returns iterator and if the element was inserted.
Definition HashTable.h:510
void erase(const const_iterator &inIterator)
Erase an element by iterator.
Definition HashTable.h:596
const_iterator begin() const
Iterator to first element.
Definition HashTable.h:474
size_type erase(const Key &inKey)
Erase an element by key.
Definition HashTable.h:613
HashTable & operator=(const HashTable &inRHS)
Assignment operator.
Definition HashTable.h:401
Fallback hash function that calls T::GetHash()
Definition HashCombine.h:59