@@ -191,6 +191,24 @@ namespace hud
191191 return hud::bits::trailing_zero (mask_value_) >> 3 ;
192192 }
193193
194+ [[nodiscard]]
195+ friend bool operator ==(const mask &a, const mask &b)
196+ {
197+ return a.mask_value_ == b.mask_value_ ;
198+ }
199+
200+ [[nodiscard]]
201+ friend bool operator !=(const mask &a, const mask &b)
202+ {
203+ return !(a == b);
204+ }
205+
206+ [[nodiscard]]
207+ constexpr operator u64 () const noexcept
208+ {
209+ return mask_value_;
210+ }
211+
194212 private:
195213 u64 mask_value_;
196214 };
@@ -227,16 +245,54 @@ namespace hud
227245 }
228246 };
229247
248+ struct full_mask
249+ : mask
250+ {
251+ using mask::mask;
252+
253+ [[nodiscard]] constexpr bool has_full_slot () const noexcept
254+ {
255+ return *this ;
256+ }
257+
258+ [[nodiscard]] constexpr u32 first_full_index () const noexcept
259+ {
260+ return first_non_null_index ();
261+ }
262+ };
263+
264+ struct full_or_sentinel_mask
265+ : mask
266+ {
267+ using mask::mask;
268+
269+ [[nodiscard]] constexpr bool has_full_slot () const noexcept
270+ {
271+ return *this ;
272+ }
273+
274+ [[nodiscard]] constexpr u32 first_full_index () const noexcept
275+ {
276+ return first_non_null_index ();
277+ }
278+ };
279+
230280 /* * Load a 8 bytes metadata into the group. */
231281 constexpr portable_group (const byte_type *metadata) noexcept
232282 : value_(hud::memory::unaligned_load64(metadata))
283+
233284 {
234285 }
235286
236287 /* *Retrieve a mask where H2 matching metadata byte have value 0x80 and non matching have value 0x00. */
237288 constexpr mask match (u8 h2_hash) const noexcept
238289 {
239- return mask {hud::bits::has_value_byte (value_, h2_hash)};
290+ // Mix of From http://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord
291+ // And http://graphics.stanford.edu/~seander/bithacks.html#ValueInWord
292+ constexpr uint64_t lsbs = 0x0101010101010101ULL ;
293+ auto x = value_ ^ (lsbs * h2_hash);
294+ return mask {(x - lsbs) & ~x & 0x8080808080808080ULL };
295+ // return mask {hud::bits::has_value_byte(value_, h2_hash)};
240296 }
241297
242298 /* * Retrieve a mask where empty metadata bytes have value 0x80 and others have value 0x00. */
@@ -296,7 +352,7 @@ namespace hud
296352 }
297353
298354 /* * Retrieve a mask where full metadata bytes have value 0x80 and others have value 0x00. */
299- constexpr u64 mask_of_full_slot () const noexcept
355+ constexpr full_mask mask_of_full_slot () const noexcept
300356 {
301357 // controls are
302358 // empty : 0b10000000
@@ -398,7 +454,7 @@ namespace hud
398454
399455 friend bool operator ==(const iterator &a, const iterator &b)
400456 {
401- return a.control_ == b.control_ ;
457+ return a.metadata_ . data () == b.metadata_ . data () ;
402458 }
403459
404460 friend bool operator !=(const iterator &a, const iterator &b)
@@ -500,7 +556,7 @@ namespace hud
500556 slot_type *slot_that_match_h2 = slots_ + slot_index_that_match_h2;
501557 if (key_equal_t {}(slot_that_match_h2->key (), key)) [[likely]]
502558 {
503- return iterator_type (metadata_.metadata_start_at_slot_index (slot_index_that_match_h2), slot_that_match_h2);
559+ return iterator_type (metadata_.metadata_that_start_at_slot_index (slot_index_that_match_h2), slot_that_match_h2);
504560 }
505561 }
506562
@@ -516,11 +572,31 @@ namespace hud
516572 }
517573 }
518574
575+ /* * Retrieves an iterator to the end of the array. */
576+ [[nodiscard]] constexpr iterator_type begin () noexcept
577+ {
578+ return find_first_full ();
579+ }
580+
581+ /* * Retrieves an iterator to the end of the array. */
582+ [[nodiscard]]
583+ constexpr const iterator_type begin () const noexcept
584+ {
585+ return find_first_full ();
586+ }
587+
519588 /* * Retrieves an iterator to the end of the array. */
520589 [[nodiscard]]
521590 constexpr iterator_type end () noexcept
522591 {
523- return iterator_type (metadata_, slots_);
592+ return iterator_type (metadata_.metadata_that_start_at_slot_index (max_slot_count_), slots_);
593+ }
594+
595+ /* * Retrieves an iterator to the end of the array. */
596+ [[nodiscard]]
597+ constexpr const iterator_type end () const noexcept
598+ {
599+ return iterator_type (metadata_.metadata_that_start_at_slot_index (max_slot_count_), slots_);
524600 }
525601
526602 private:
@@ -619,8 +695,11 @@ namespace hud
619695 {
620696 // Move elements to new buffer if any
621697 // Relocate slots to newly allocated buffer
698+ // for (auto &slot : *this)
699+ // {
700+ // find_first_empty_or_deleted()
701+ // }
622702 // Free old buffer
623-
624703 allocator_.template free <slot_type>({hud::bit_cast<slot_type *>(metadata_.data ()), current_allocation_size ()});
625704 }
626705
@@ -675,6 +754,27 @@ namespace hud
675754 }
676755 }
677756
757+ [[nodiscard]]
758+ constexpr iterator_type find_first_full () noexcept
759+ {
760+ hud::check (hud::bits::is_valid_power_of_two_mask (max_slot_count_) && " Not a mask" );
761+ usize slot_index = 0 ;
762+ while (slot_index < max_slot_count_)
763+ {
764+ metadata::group_type group = metadata_.group_of_slot_index (slot_index);
765+ metadata::group_type::full_mask group_mask = group.mask_of_full_slot ();
766+ if (group_mask.has_full_slot ())
767+ {
768+ u32 first_full_index = group_mask.first_full_index ();
769+ return iterator_type {metadata_.metadata_that_start_at_slot_index (first_full_index), slots_ + first_full_index};
770+ }
771+
772+ // Advance to next group (Maybe a metadata iterator that iterate over groups can be better alternative)
773+ slot_index += metadata::group_type::SLOT_PER_GROUP;
774+ }
775+ return end ();
776+ }
777+
678778 /* *
679779 * Compute the maximum number of slots we should put into the table before a resizing rehash.
680780 * Subtract the returned value with the number of slots `count()` to obtains the number of slots we can currently before a resizing rehash.
@@ -721,7 +821,8 @@ namespace hud
721821 typename key_equal_t = details::hashset::default_equal<value_t >,
722822 typename allocator_t = details::hashset::default_allocator<value_t >>
723823 class hashset
724- : details::hashset::hashset_impl<details::hashset::slot<value_t >, hasher_t , key_equal_t , allocator_t >
824+ : public details::hashset::hashset_impl<details::hashset::slot<value_t >, hasher_t , key_equal_t , allocator_t >
825+
725826 {
726827 private:
727828 using super = details::hashset::hashset_impl<details::hashset::slot<value_t >, hasher_t , key_equal_t , allocator_t >;
@@ -731,10 +832,6 @@ namespace hud
731832 using hasher_type = typename super::hasher_type;
732833 /* * Type of the value. */
733834 using value_type = typename super::value_type;
734-
735- /* * Import super functions. */
736- using super::insert_to_ref;
737- using super::super;
738835 };
739836} // namespace hud
740837
0 commit comments