@@ -635,30 +635,49 @@ template <class ElemTy> struct ConcurrentReadableHashMap {
635
635
std::atomic<Index> &at (size_t i) { return (&Mask)[i]; }
636
636
};
637
637
638
+ // / A simple linked list representing pointers that need to be freed.
639
+ struct FreeListNode {
640
+ FreeListNode *Next;
641
+ void *Ptr;
642
+
643
+ static void add (FreeListNode **head, void *ptr) {
644
+ auto *newNode = new FreeListNode{*head, ptr};
645
+ *head = newNode;
646
+ }
647
+
648
+ static void freeAll (FreeListNode **head) {
649
+ auto *node = *head;
650
+ while (node) {
651
+ auto *next = node->Next ;
652
+ free (node->Ptr );
653
+ delete node;
654
+ node = next;
655
+ }
656
+ *head = nullptr ;
657
+ }
658
+ };
659
+
638
660
// / The number of readers currently active, equal to the number of snapshot
639
661
// / objects currently alive.
640
- std::atomic<size_t > ReaderCount;
662
+ std::atomic<uint32_t > ReaderCount{ 0 } ;
641
663
642
664
// / The number of elements in the elements array.
643
- std::atomic<size_t > ElementCount;
665
+ std::atomic<uint32_t > ElementCount{ 0 } ;
644
666
645
667
// / The array of elements.
646
- std::atomic<ElemTy *> Elements;
668
+ std::atomic<ElemTy *> Elements{ nullptr } ;
647
669
648
670
// / The array of indices.
649
- std::atomic<IndexStorage *> Indices;
671
+ std::atomic<IndexStorage *> Indices{ nullptr } ;
650
672
651
673
// / The writer lock, which must be taken before any mutation of the table.
652
674
Mutex WriterLock;
653
675
654
676
// / The maximum number of elements that the current elements array can hold.
655
- size_t ElementCapacity;
677
+ uint32_t ElementCapacity{ 0 } ;
656
678
657
- // / The list of element arrays to be freed once no readers are active.
658
- std::vector<ElemTy *> ElementFreeList;
659
-
660
- // / The list of index arrays to be freed once no readers are active.
661
- std::vector<IndexStorage *> IndicesFreeList;
679
+ // / The list of pointers to be freed once no readers are active.
680
+ FreeListNode *FreeList{nullptr };
662
681
663
682
void incrementReaders () {
664
683
ReaderCount.fetch_add (1 , std::memory_order_acquire);
@@ -668,24 +687,11 @@ template <class ElemTy> struct ConcurrentReadableHashMap {
668
687
ReaderCount.fetch_sub (1 , std::memory_order_release);
669
688
}
670
689
671
- // / Free all the arrays in the free lists.
672
- void deallocateFreeList () {
673
- for (auto *storage : ElementFreeList)
674
- free (storage);
675
- ElementFreeList.clear ();
676
- ElementFreeList.shrink_to_fit ();
677
-
678
- for (auto *indices : IndicesFreeList)
679
- free (indices);
680
- IndicesFreeList.clear ();
681
- IndicesFreeList.shrink_to_fit ();
682
- }
683
-
684
690
// / Free all the arrays in the free lists if there are no active readers. If
685
691
// / there are active readers, do nothing.
686
692
void deallocateFreeListIfSafe () {
687
693
if (ReaderCount.load (std::memory_order_acquire) == 0 )
688
- deallocateFreeList ( );
694
+ FreeListNode::freeAll (&FreeList );
689
695
}
690
696
691
697
// / Grow the elements array, adding the old array to the free list and
@@ -702,7 +708,7 @@ template <class ElemTy> struct ConcurrentReadableHashMap {
702
708
ElemTy *newElements = static_cast <ElemTy *>(malloc (newSize));
703
709
if (elements) {
704
710
memcpy (newElements, elements, elementCount * sizeof (ElemTy));
705
- ElementFreeList. push_back ( elements);
711
+ FreeListNode::add (&FreeList, elements);
706
712
}
707
713
708
714
ElementCapacity = newCapacity;
@@ -739,7 +745,7 @@ template <class ElemTy> struct ConcurrentReadableHashMap {
739
745
740
746
Indices.store (newIndices, std::memory_order_release);
741
747
742
- IndicesFreeList. push_back ( indices);
748
+ FreeListNode::add (&FreeList, indices);
743
749
744
750
return newIndices;
745
751
}
@@ -792,7 +798,7 @@ template <class ElemTy> struct ConcurrentReadableHashMap {
792
798
~ConcurrentReadableHashMap () {
793
799
assert (ReaderCount.load (std::memory_order_acquire) == 0 &&
794
800
" deallocating ConcurrentReadableHashMap with outstanding snapshots" );
795
- deallocateFreeList ( );
801
+ FreeListNode::freeAll (&FreeList );
796
802
}
797
803
798
804
// / Readers take a snapshot of the hash map, then work with the snapshot.
@@ -943,8 +949,8 @@ template <class ElemTy> struct ConcurrentReadableHashMap {
943
949
Elements.store (nullptr , std::memory_order_relaxed);
944
950
ElementCapacity = 0 ;
945
951
946
- IndicesFreeList. push_back ( indices);
947
- ElementFreeList. push_back ( elements);
952
+ FreeListNode::add (&FreeList, indices);
953
+ FreeListNode::add (&FreeList, elements);
948
954
949
955
deallocateFreeListIfSafe ();
950
956
}
0 commit comments