@@ -200,14 +200,14 @@ namespace hud
200200 }
201201 };
202202
203- /* * Load a 8 bytes metadata into the group. */
204- constexpr portable_group (const control_type *metadata ) noexcept
205- : value_(hud::memory::unaligned_load64(metadata ))
203+ /* * Load a 8 bytes control into the group. */
204+ constexpr portable_group (const control_type *control ) noexcept
205+ : value_(hud::memory::unaligned_load64(control ))
206206
207207 {
208208 }
209209
210- /* *Retrieve a mask where H2 matching metadata byte have value 0x80 and non matching have value 0x00. */
210+ /* *Retrieve a mask where H2 matching control byte have value 0x80 and non matching have value 0x00. */
211211 constexpr mask match (u8 h2_hash) const noexcept
212212 {
213213 // Mix of From http://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord
@@ -217,7 +217,7 @@ namespace hud
217217 return mask {(x - lsbs) & ~x & 0x8080808080808080ULL };
218218 }
219219
220- /* * Retrieve a mask where empty metadata bytes have value 0x80 and others have value 0x00. */
220+ /* * Retrieve a mask where empty control bytes have value 0x80 and others have value 0x00. */
221221 constexpr empty_mask mask_of_empty_slot () const noexcept
222222 {
223223 // controls are
@@ -246,7 +246,7 @@ namespace hud
246246 return (value_ & ~(value_ << 6 )) & 0x8080808080808080UL ;
247247 }
248248
249- /* * Retrieve a mask where empty and deleted metadata bytes have value 0x80 and others have value 0x00. */
249+ /* * Retrieve a mask where empty and deleted control bytes have value 0x80 and others have value 0x00. */
250250 constexpr empty_or_deleted_mask mask_of_empty_or_deleted_slot () const noexcept
251251 {
252252 // controls are
@@ -273,7 +273,7 @@ namespace hud
273273 return (value_ & ~(value_ << 7 )) & 0x8080808080808080UL ;
274274 }
275275
276- /* * Retrieve a mask where full metadata bytes have value 0x80 and others have value 0x00. */
276+ /* * Retrieve a mask where full control bytes have value 0x80 and others have value 0x00. */
277277 constexpr full_mask mask_of_full_slot () const noexcept
278278 {
279279 // controls are
@@ -309,7 +309,7 @@ namespace hud
309309 u64 value_;
310310 };
311311
312- /* * Group type used to iterate over the metadata . */
312+ /* * Group type used to iterate over the control . */
313313 using group_type = portable_group;
314314
315315 alignas (16 ) constexpr const control_type INIT_GROUP[32 ] {
@@ -361,33 +361,40 @@ namespace hud
361361 control_ptr[((slot_index - COUNT_CLONED_BYTE) & max_slot_count) + (COUNT_CLONED_BYTE & max_slot_count)] = h2;
362362 }
363363
364- /* * Check if the metadata byte is empty. */
364+ /* * Check if the control byte is empty. */
365365 [[nodiscard]]
366366 static constexpr bool is_byte_empty (control_type byte_value) noexcept
367367 {
368368 return byte_value == empty_byte;
369369 }
370370
371- /* * Check if the metadata byte is deleted. */
371+ /* * Check if the control byte is deleted. */
372372 [[nodiscard]]
373373 static constexpr bool is_byte_deleted (control_type byte_value) noexcept
374374 {
375375 return byte_value == deleted_byte;
376376 }
377377
378- /* * Check if the metadata byte is empty or deleted. */
378+ /* * Check if the control byte is empty or deleted. */
379379 [[nodiscard]]
380380 static constexpr bool is_byte_empty_or_deleted (control_type byte_value) noexcept
381381 {
382382 return byte_value < sentinel_byte;
383383 }
384384
385- /* * Check if the metadata byte is full. */
385+ /* * Check if the control byte is full. */
386386 [[nodiscard]]
387387 static constexpr bool is_byte_full (control_type byte_value) noexcept
388388 {
389389 return byte_value >= 0 ;
390390 }
391+
392+ /* * Check if the control byte is deleted. */
393+ [[nodiscard]]
394+ static constexpr bool is_byte_sentinel (control_type byte_value) noexcept
395+ {
396+ return byte_value == sentinel_byte;
397+ }
391398 };
392399
393400 /* * The hashmap iterator that iterate over elements. */
@@ -466,7 +473,7 @@ namespace hud
466473 }
467474
468475 private:
469- // The metadata to iterate over
476+ // The control to iterate over
470477 control_type *control_ptr_;
471478 // The current slot we are iterating. Keep uninitialized.
472479 slot_type *slot_ptr_;
@@ -620,7 +627,7 @@ namespace hud
620627 return end ();
621628 }
622629
623- // Advance to next group (Maybe a metadata iterator taht iterate over groups can be better alternative)
630+ // Advance to next group (Maybe a control iterator taht iterate over groups can be better alternative)
624631 slot_index += group_type::SLOT_PER_GROUP;
625632 slot_index &= max_slot_count_;
626633 }
@@ -664,7 +671,7 @@ namespace hud
664671
665672 /* * Retrieves an iterator to the end of the array. */
666673 [[nodiscard]]
667- constexpr const iterator begin () const noexcept
674+ constexpr const_iterator begin () const noexcept
668675 {
669676 return find_first_full ();
670677 }
@@ -673,14 +680,14 @@ namespace hud
673680 [[nodiscard]]
674681 constexpr iterator end () noexcept
675682 {
676- return iterator (control_ptr_ + max_slot_count_ );
683+ return iterator (control_ptr_sentinel () );
677684 }
678685
679686 /* * Retrieves an iterator to the end of the array. */
680687 [[nodiscard]]
681- constexpr const iterator end () const noexcept
688+ constexpr const_iterator end () const noexcept
682689 {
683- return iterator (control_ptr_ + max_slot_count_ );
690+ return iterator (control_ptr_sentinel () );
684691 }
685692
686693 private:
@@ -750,53 +757,52 @@ namespace hud
750757
751758 // Create the buffer with control and slots
752759 // Slots are aligned on alignof(slot_type)
760+ control_type *old_control_ptr = control_ptr_;
761+ slot_type *old_slot_ptr = slot_ptr_;
762+ usize old_max_slot_count = max_slot_count_;
763+ max_slot_count_ = new_max_slot_count;
753764
754765 // We cloned size of a group - 1 because we never reach the last cloned bytes
755766 constexpr const usize num_cloned_bytes = control::COUNT_CLONED_BYTE;
756767 // Control size is the number of slot + sentinel + number of cloned bytes
757- const usize control_size = new_max_slot_count + 1 + num_cloned_bytes;
768+ const usize control_size = max_slot_count_ + 1 + num_cloned_bytes;
758769 const uptr aligned_control_size = hud::memory::align_address (control_size, sizeof (slot_type));
759- const usize aligned_allocation_size = aligned_control_size + new_max_slot_count * sizeof (slot_type);
760-
761- // Allocate the buffer that will contains controls and aligned slots
762- memory_allocation_type allocation = allocator_.template allocate <slot_type>(aligned_allocation_size);
770+ const usize aligned_allocation_size = aligned_control_size + max_slot_count_ * sizeof (slot_type);
763771
764- // Save control and slot pointers
765- control_type *new_control_ptr = hud::bit_cast<control_type *>(allocation .data ());
766- slot_type *new_slot_ptr = hud::bit_cast<slot_type *>(new_control_ptr + aligned_control_size);
767- hud::check (hud::memory::is_pointer_aligned (new_slot_ptr , alignof (slot_type)));
772+ // Allocate the buffer that will contains controls and aligned slots
773+ control_ptr_ = hud::bit_cast<control_type *>(allocator_. template allocate <slot_type>(aligned_allocation_size) .data ());
774+ slot_ptr_ = hud::bit_cast<slot_type *>(control_ptr_ + aligned_control_size);
775+ hud::check (hud::memory::is_pointer_aligned (slot_ptr_ , alignof (slot_type)));
768776
769777 // Update number of slot we should put into the table before a resizing rehash
770- free_slot_before_grow_ = max_slot_before_grow (new_max_slot_count ) - count_;
778+ free_slot_before_grow_ = max_slot_before_grow (max_slot_count_ ) - count_;
771779
772- // Reset control metadata
773- hud::memory::set (new_control_ptr , control_size, empty_byte);
774- new_control_ptr[new_max_slot_count ] = sentinel_byte;
780+ // Set control to empty ending with sentinel
781+ hud::memory::set (control_ptr_ , control_size, empty_byte);
782+ control_ptr_[max_slot_count_ ] = sentinel_byte;
775783
776784 // If we have elements, insert them to the new buffer
777785 if (count_ > 0 )
778786 {
779787 // Move elements to new buffer if any
780788 // Relocate slots to newly allocated buffer
781- for (auto &slot : *this )
789+ for (auto it = const_iterator {old_control_ptr, old_slot_ptr};
790+ it != const_iterator (old_control_ptr + old_max_slot_count);
791+ ++it)
782792 {
783793 // Compute the hash
784- u64 hash = hasher_type {}(slot. key ());
794+ u64 hash = hasher_type {}(it-> key ());
785795 // Find H1 slot index
786796 u64 h1 = H1 (hash);
787- usize slot_index = find_first_empty_or_deleted (new_control_ptr, new_max_slot_count , h1);
797+ usize slot_index = find_first_empty_or_deleted (control_ptr_, old_max_slot_count , h1);
788798 // Save h2 in control h1 index
789- control::set_h2 (new_control_ptr , slot_index, H2 (hash), new_max_slot_count );
799+ control::set_h2 (control_ptr_ , slot_index, H2 (hash), old_max_slot_count );
790800 // Move old slot to new slot
791- hud::memory::move_or_copy_construct_then_destroy (new_slot_ptr + slot_index, hud::move (slot ));
801+ hud::memory::move_or_copy_construct_then_destroy (slot_ptr_ + slot_index, hud::move (*it ));
792802 }
793803 // Free old buffer
794- allocator_.template free <slot_type>({hud::bit_cast<slot_type *>(control_ptr_ ), current_allocation_size ()});
804+ allocator_.template free <slot_type>({hud::bit_cast<slot_type *>(old_control_ptr ), current_allocation_size ()});
795805 }
796-
797- control_ptr_ = new_control_ptr;
798- slot_ptr_ = new_slot_ptr;
799- max_slot_count_ = new_max_slot_count;
800806 }
801807
802808 [[nodiscard]] constexpr usize free_slot_before_grow () const noexcept
@@ -860,7 +866,7 @@ namespace hud
860866 return {control_ptr_ + first_full_index, slot_ptr_ + first_full_index};
861867 }
862868
863- // Advance to next group (Maybe a metadata iterator that iterate over groups can be better alternative)
869+ // Advance to next group (Maybe a control iterator that iterate over groups can be better alternative)
864870 slot_index += group_type::SLOT_PER_GROUP;
865871 }
866872 return end ();
@@ -884,8 +890,15 @@ namespace hud
884890 return group_type::SLOT_PER_GROUP == 8 && capacity == 7 ? 6 : capacity - capacity / 8 ;
885891 }
886892
893+ [[nodiscard]]
894+ constexpr control_type *control_ptr_sentinel () const noexcept
895+ {
896+ hud::check (control::is_byte_sentinel (control_ptr_[max_slot_count_]));
897+ return control_ptr_ + max_slot_count_;
898+ }
899+
887900 private:
888- /* * The metadata of the hashmap. */
901+ /* * The control of the hashmap. */
889902 control_type *control_ptr_ {const_cast <control_type *>(&INIT_GROUP[16 ])};
890903
891904 /* * Pointer to the slot segment. */
0 commit comments