@@ -383,7 +383,12 @@ class open_addressing_ref_impl {
383383 auto probing_iter = probing_scheme_ (key, storage_ref_.bucket_extent ());
384384 auto const init_idx = *probing_iter;
385385
386+ [[maybe_unused]] auto probing_iter_copy = probing_iter;
387+ [[maybe_unused]] bool erased = false ;
388+ [[maybe_unused]] bool empty_after_erased = false ;
389+
386390 while (true ) {
391+ [[maybe_unused]] continue_after_erased:
387392 auto const bucket_slots = storage_ref_[*probing_iter];
388393
389394 for (auto & slot_content : bucket_slots) {
@@ -393,23 +398,54 @@ class open_addressing_ref_impl {
393398 if constexpr (not allows_duplicates) {
394399 // If the key is already in the container, return false
395400 if (eq_res == detail::equal_result::EQUAL) { return false ; }
401+ if (eq_res == detail::equal_result::ERASED and not erased and not empty_after_erased) {
402+ erased = true ;
403+ probing_iter_copy = probing_iter;
404+ }
405+ if (eq_res == detail::equal_result::EMPTY and erased and not empty_after_erased) {
406+ empty_after_erased = true ;
407+ probing_iter = probing_iter_copy;
408+ goto continue_after_erased;
409+ }
396410 }
397- if (eq_res == detail::equal_result::AVAILABLE) {
398- auto const intra_bucket_index = thrust::distance (bucket_slots.begin (), &slot_content);
399- switch (attempt_insert ((storage_ref_.data () + *probing_iter)->data () + intra_bucket_index,
400- slot_content,
401- val)) {
402- case insert_result::DUPLICATE: {
403- if constexpr (allows_duplicates) {
404- [[fallthrough]];
405- } else {
406- return false ;
411+
412+ if (not erased or empty_after_erased) {
413+ if ((eq_res == detail::equal_result::EMPTY) or (eq_res == detail::equal_result::ERASED)) {
414+ auto const intra_bucket_index = thrust::distance (bucket_slots.begin (), &slot_content);
415+ switch (
416+ attempt_insert ((storage_ref_.data () + *probing_iter)->data () + intra_bucket_index,
417+ slot_content,
418+ val)) {
419+ case insert_result::DUPLICATE: {
420+ if constexpr (allows_duplicates) {
421+ [[fallthrough]];
422+ } else {
423+ return false ;
424+ }
407425 }
426+ case insert_result::CONTINUE: continue ;
427+ case insert_result::SUCCESS: return true ;
408428 }
409- case insert_result::CONTINUE: continue ;
410- case insert_result::SUCCESS: return true ;
411429 }
412430 }
431+
432+ // if (eq_res == detail::equal_result::AVAILABLE) {
433+ // auto const intra_bucket_index = thrust::distance(bucket_slots.begin(), &slot_content);
434+ // switch (attempt_insert((storage_ref_.data() + *probing_iter)->data() +
435+ // intra_bucket_index,
436+ // slot_content,
437+ // val)) {
438+ // case insert_result::DUPLICATE: {
439+ // if constexpr (allows_duplicates) {
440+ // [[fallthrough]];
441+ // } else {
442+ // return false;
443+ // }
444+ // }
445+ // case insert_result::CONTINUE: continue;
446+ // case insert_result::SUCCESS: return true;
447+ // }
448+ // }
413449 }
414450 ++probing_iter;
415451 if (*probing_iter == init_idx) { return false ; }
@@ -442,8 +478,10 @@ class open_addressing_ref_impl {
442478 for (auto i = 0 ; i < bucket_size; ++i) {
443479 switch (
444480 this ->predicate_ .operator ()<is_insert::YES>(key, this ->extract_key (bucket_slots[i]))) {
445- case detail::equal_result::AVAILABLE:
446- return bucket_probing_results{detail::equal_result::AVAILABLE, i};
481+ case detail::equal_result::EMPTY:
482+ return bucket_probing_results{detail::equal_result::EMPTY, i};
483+ case detail::equal_result::ERASED:
484+ return bucket_probing_results{detail::equal_result::ERASED, i};
447485 case detail::equal_result::EQUAL: {
448486 if constexpr (allows_duplicates) {
449487 continue ;
@@ -463,7 +501,8 @@ class open_addressing_ref_impl {
463501 if (group.any (state == detail::equal_result::EQUAL)) { return false ; }
464502 }
465503
466- auto const group_contains_available = group.ballot (state == detail::equal_result::AVAILABLE);
504+ auto const group_contains_available = group.ballot ((state == detail::equal_result::EMPTY) or
505+ (state == detail::equal_result::ERASED));
467506 if (group_contains_available) {
468507 auto const src_lane = __ffs (group_contains_available) - 1 ;
469508 auto const status =
@@ -538,7 +577,7 @@ class open_addressing_ref_impl {
538577 }
539578 return {iterator{&bucket_ptr[i]}, false };
540579 }
541- if (eq_res == detail::equal_result::AVAILABLE ) {
580+ if (( eq_res == detail::equal_result::EMPTY) or (eq_res == detail::equal_result::ERASED) ) {
542581 switch (this ->attempt_insert_stable (bucket_ptr + i, bucket_slots[i], val)) {
543582 case insert_result::SUCCESS: {
544583 if constexpr (has_payload) {
@@ -626,7 +665,8 @@ class open_addressing_ref_impl {
626665 return {iterator{reinterpret_cast <value_type*>(res)}, false };
627666 }
628667
629- auto const group_contains_available = group.ballot (state == detail::equal_result::AVAILABLE);
668+ auto const group_contains_available = group.ballot ((state == detail::equal_result::EMPTY) or
669+ (state == detail::equal_result::ERASED));
630670 if (group_contains_available) {
631671 auto const src_lane = __ffs (group_contains_available) - 1 ;
632672 auto const res = group.shfl (reinterpret_cast <intptr_t >(slot_ptr), src_lane);
0 commit comments