@@ -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,21 +398,34 @@ 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 }
413431 }
@@ -442,8 +460,10 @@ class open_addressing_ref_impl {
442460 for (auto i = 0 ; i < bucket_size; ++i) {
443461 switch (
444462 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};
463+ case detail::equal_result::EMPTY:
464+ return bucket_probing_results{detail::equal_result::EMPTY, i};
465+ case detail::equal_result::ERASED:
466+ return bucket_probing_results{detail::equal_result::ERASED, i};
447467 case detail::equal_result::EQUAL: {
448468 if constexpr (allows_duplicates) {
449469 continue ;
@@ -463,7 +483,8 @@ class open_addressing_ref_impl {
463483 if (group.any (state == detail::equal_result::EQUAL)) { return false ; }
464484 }
465485
466- auto const group_contains_available = group.ballot (state == detail::equal_result::AVAILABLE);
486+ auto const group_contains_available = group.ballot ((state == detail::equal_result::EMPTY) or
487+ (state == detail::equal_result::ERASED));
467488 if (group_contains_available) {
468489 auto const src_lane = __ffs (group_contains_available) - 1 ;
469490 auto const status =
@@ -538,7 +559,7 @@ class open_addressing_ref_impl {
538559 }
539560 return {iterator{&bucket_ptr[i]}, false };
540561 }
541- if (eq_res == detail::equal_result::AVAILABLE ) {
562+ if (( eq_res == detail::equal_result::EMPTY) or (eq_res == detail::equal_result::ERASED) ) {
542563 switch (this ->attempt_insert_stable (bucket_ptr + i, bucket_slots[i], val)) {
543564 case insert_result::SUCCESS: {
544565 if constexpr (has_payload) {
@@ -626,7 +647,8 @@ class open_addressing_ref_impl {
626647 return {iterator{reinterpret_cast <value_type*>(res)}, false };
627648 }
628649
629- auto const group_contains_available = group.ballot (state == detail::equal_result::AVAILABLE);
650+ auto const group_contains_available = group.ballot ((state == detail::equal_result::EMPTY) or
651+ (state == detail::equal_result::ERASED));
630652 if (group_contains_available) {
631653 auto const src_lane = __ffs (group_contains_available) - 1 ;
632654 auto const res = group.shfl (reinterpret_cast <intptr_t >(slot_ptr), src_lane);
0 commit comments