@@ -593,51 +593,6 @@ struct ConcurrentReadableHashMap {
593
593
}
594
594
}
595
595
596
- // Common implementation for `getOrInsert` and `GetOrInsertManyScope`
597
- template <class KeyTy , typename Call>
598
- void getOrInsertExternallyLocked (KeyTy key, const Call &call) {
599
- auto indices = IndexStorage{Indices.load (std::memory_order_relaxed)};
600
- auto indicesCapacityLog2 = indices.getCapacityLog2 ();
601
- auto elementCount = ElementCount.load (std::memory_order_relaxed);
602
- auto *elements = Elements.load (std::memory_order_relaxed);
603
- auto *elementsPtr = elements ? elements->data () : nullptr ;
604
-
605
-
606
- auto found = this ->find (key, indices, elementCount, elementsPtr);
607
- if (found.first ) {
608
- call (found.first , false );
609
- return ;
610
- }
611
-
612
- auto indicesCapacity = 1UL << indicesCapacityLog2;
613
-
614
- // The number of slots in use is elementCount + 1, since the capacity also
615
- // takes a slot.
616
- auto emptyCount = indicesCapacity - (elementCount + 1 );
617
- auto proportion = indicesCapacity / emptyCount;
618
- if (proportion >= ResizeProportion) {
619
- indices = resize (indices, indicesCapacityLog2, elementsPtr);
620
- found = find (key, indices, elementCount, elementsPtr);
621
- assert (!found.first && " Shouldn't suddenly find the key after rehashing" );
622
- }
623
-
624
- if (!elements || elementCount >= elements->Capacity ) {
625
- elements = resize (elements, elementCount);
626
- }
627
- auto *element = &elements->data ()[elementCount];
628
-
629
- // Order matters: fill out the element, then update the count,
630
- // then update the index.
631
- bool keep = call (element, true );
632
- if (keep) {
633
- assert (hash_value (key) == hash_value (*element) &&
634
- " Element must have the same hash code as its key." );
635
- ElementCount.store (elementCount + 1 , std::memory_order_release);
636
- indices.storeIndexAt (&Indices, elementCount + 1 , found.second ,
637
- std::memory_order_release);
638
- }
639
- }
640
-
641
596
public:
642
597
// Implicitly trivial constructor/destructor.
643
598
ConcurrentReadableHashMap () = default ;
@@ -729,48 +684,6 @@ struct ConcurrentReadableHashMap {
729
684
return Snapshot (this , indices, elementsPtr, elementCount);
730
685
}
731
686
732
- // / A wrapper that allows performing several `getOrInsert` operations under
733
- // / the same lock.
734
- class GetOrInsertManyScope {
735
- GetOrInsertManyScope () = delete ;
736
- GetOrInsertManyScope (const GetOrInsertManyScope &) = delete ;
737
- GetOrInsertManyScope &operator =(const GetOrInsertManyScope &) = delete ;
738
- GetOrInsertManyScope (GetOrInsertManyScope &&) = delete ;
739
- GetOrInsertManyScope &operator =(GetOrInsertManyScope &&) = delete ;
740
-
741
- ConcurrentReadableHashMap ⤅
742
-
743
- public:
744
- GetOrInsertManyScope (ConcurrentReadableHashMap &map) : Map(map) {
745
- Map.WriterLock .lock ();
746
- }
747
-
748
- ~GetOrInsertManyScope () {
749
- Map.deallocateFreeListIfSafe ();
750
- Map.WriterLock .unlock ();
751
- }
752
-
753
- // / Get an element by key, or insert a new element for that key if one is
754
- // / not already present. Invoke `call` with the pointer to the element.
755
- // /
756
- // / `call` is passed the following parameters:
757
- // / - `element`: the pointer to the element corresponding to `key`
758
- // / - `created`: true if the element is newly created, false if it already
759
- // / exists
760
- // / `call` returns a `bool`. When `created` is `true`, the return values
761
- // / mean:
762
- // / - `true` the new entry is to be kept
763
- // / - `false` indicates that the new entry is discarded
764
- // / If the new entry is kept, then the new element MUST be initialized, and
765
- // / have a hash value that matches the hash value of `key`.
766
- // /
767
- // / The return value is ignored when `created` is `false`.
768
- template <class KeyTy , typename Call>
769
- void getOrInsert (KeyTy key, const Call &call) {
770
- Map.getOrInsertExternallyLocked (key, call);
771
- }
772
- };
773
-
774
687
// / Get an element by key, or insert a new element for that key if one is not
775
688
// / already present. Invoke `call` with the pointer to the element. BEWARE:
776
689
// / `call` is invoked with the internal writer lock held, keep work to a
@@ -790,7 +703,48 @@ struct ConcurrentReadableHashMap {
790
703
template <class KeyTy , typename Call>
791
704
void getOrInsert (KeyTy key, const Call &call) {
792
705
typename MutexTy::ScopedLock guard (WriterLock);
793
- getOrInsertExternallyLocked (key, call);
706
+
707
+ auto indices = IndexStorage{Indices.load (std::memory_order_relaxed)};
708
+ auto indicesCapacityLog2 = indices.getCapacityLog2 ();
709
+ auto elementCount = ElementCount.load (std::memory_order_relaxed);
710
+ auto *elements = Elements.load (std::memory_order_relaxed);
711
+ auto *elementsPtr = elements ? elements->data () : nullptr ;
712
+
713
+ auto found = this ->find (key, indices, elementCount, elementsPtr);
714
+ if (found.first ) {
715
+ call (found.first , false );
716
+ deallocateFreeListIfSafe ();
717
+ return ;
718
+ }
719
+
720
+ auto indicesCapacity = 1UL << indicesCapacityLog2;
721
+
722
+ // The number of slots in use is elementCount + 1, since the capacity also
723
+ // takes a slot.
724
+ auto emptyCount = indicesCapacity - (elementCount + 1 );
725
+ auto proportion = indicesCapacity / emptyCount;
726
+ if (proportion >= ResizeProportion) {
727
+ indices = resize (indices, indicesCapacityLog2, elementsPtr);
728
+ found = find (key, indices, elementCount, elementsPtr);
729
+ assert (!found.first && " Shouldn't suddenly find the key after rehashing" );
730
+ }
731
+
732
+ if (!elements || elementCount >= elements->Capacity ) {
733
+ elements = resize (elements, elementCount);
734
+ }
735
+ auto *element = &elements->data ()[elementCount];
736
+
737
+ // Order matters: fill out the element, then update the count,
738
+ // then update the index.
739
+ bool keep = call (element, true );
740
+ if (keep) {
741
+ assert (hash_value (key) == hash_value (*element) &&
742
+ " Element must have the same hash code as its key." );
743
+ ElementCount.store (elementCount + 1 , std::memory_order_release);
744
+ indices.storeIndexAt (&Indices, elementCount + 1 , found.second ,
745
+ std::memory_order_release);
746
+ }
747
+
794
748
deallocateFreeListIfSafe ();
795
749
}
796
750
0 commit comments