@@ -383,7 +383,12 @@ class open_addressing_ref_impl {
383
383
auto probing_iter = probing_scheme_ (key, storage_ref_.bucket_extent ());
384
384
auto const init_idx = *probing_iter;
385
385
386
+ [[maybe_unused]] auto probing_iter_copy = probing_iter;
387
+ [[maybe_unused]] bool erased = false ;
388
+ [[maybe_unused]] bool empty_after_erased = false ;
389
+
386
390
while (true ) {
391
+ [[maybe_unused]] continue_after_erased:
387
392
auto const bucket_slots = storage_ref_[*probing_iter];
388
393
389
394
for (auto & slot_content : bucket_slots) {
@@ -393,23 +398,54 @@ class open_addressing_ref_impl {
393
398
if constexpr (not allows_duplicates) {
394
399
// If the key is already in the container, return false
395
400
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
+ }
396
410
}
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
+ }
407
425
}
426
+ case insert_result::CONTINUE: continue ;
427
+ case insert_result::SUCCESS: return true ;
408
428
}
409
- case insert_result::CONTINUE: continue ;
410
- case insert_result::SUCCESS: return true ;
411
429
}
412
430
}
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
+ // }
413
449
}
414
450
++probing_iter;
415
451
if (*probing_iter == init_idx) { return false ; }
@@ -442,8 +478,10 @@ class open_addressing_ref_impl {
442
478
for (auto i = 0 ; i < bucket_size; ++i) {
443
479
switch (
444
480
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};
447
485
case detail::equal_result::EQUAL: {
448
486
if constexpr (allows_duplicates) {
449
487
continue ;
@@ -463,7 +501,8 @@ class open_addressing_ref_impl {
463
501
if (group.any (state == detail::equal_result::EQUAL)) { return false ; }
464
502
}
465
503
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));
467
506
if (group_contains_available) {
468
507
auto const src_lane = __ffs (group_contains_available) - 1 ;
469
508
auto const status =
@@ -538,7 +577,7 @@ class open_addressing_ref_impl {
538
577
}
539
578
return {iterator{&bucket_ptr[i]}, false };
540
579
}
541
- if (eq_res == detail::equal_result::AVAILABLE ) {
580
+ if (( eq_res == detail::equal_result::EMPTY) or (eq_res == detail::equal_result::ERASED) ) {
542
581
switch (this ->attempt_insert_stable (bucket_ptr + i, bucket_slots[i], val)) {
543
582
case insert_result::SUCCESS: {
544
583
if constexpr (has_payload) {
@@ -626,7 +665,8 @@ class open_addressing_ref_impl {
626
665
return {iterator{reinterpret_cast <value_type*>(res)}, false };
627
666
}
628
667
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));
630
670
if (group_contains_available) {
631
671
auto const src_lane = __ffs (group_contains_available) - 1 ;
632
672
auto const res = group.shfl (reinterpret_cast <intptr_t >(slot_ptr), src_lane);
0 commit comments