@@ -635,30 +635,49 @@ template <class ElemTy> struct ConcurrentReadableHashMap {
635635 std::atomic<Index> &at (size_t i) { return (&Mask)[i]; }
636636 };
637637
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+
638660 // / The number of readers currently active, equal to the number of snapshot
639661 // / objects currently alive.
640- std::atomic<size_t > ReaderCount;
662+ std::atomic<uint32_t > ReaderCount{ 0 } ;
641663
642664 // / The number of elements in the elements array.
643- std::atomic<size_t > ElementCount;
665+ std::atomic<uint32_t > ElementCount{ 0 } ;
644666
645667 // / The array of elements.
646- std::atomic<ElemTy *> Elements;
668+ std::atomic<ElemTy *> Elements{ nullptr } ;
647669
648670 // / The array of indices.
649- std::atomic<IndexStorage *> Indices;
671+ std::atomic<IndexStorage *> Indices{ nullptr } ;
650672
651673 // / The writer lock, which must be taken before any mutation of the table.
652674 Mutex WriterLock;
653675
654676 // / The maximum number of elements that the current elements array can hold.
655- size_t ElementCapacity;
677+ uint32_t ElementCapacity{ 0 } ;
656678
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 };
662681
663682 void incrementReaders () {
664683 ReaderCount.fetch_add (1 , std::memory_order_acquire);
@@ -668,24 +687,11 @@ template <class ElemTy> struct ConcurrentReadableHashMap {
668687 ReaderCount.fetch_sub (1 , std::memory_order_release);
669688 }
670689
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-
684690 // / Free all the arrays in the free lists if there are no active readers. If
685691 // / there are active readers, do nothing.
686692 void deallocateFreeListIfSafe () {
687693 if (ReaderCount.load (std::memory_order_acquire) == 0 )
688- deallocateFreeList ( );
694+ FreeListNode::freeAll (&FreeList );
689695 }
690696
691697 // / Grow the elements array, adding the old array to the free list and
@@ -702,7 +708,7 @@ template <class ElemTy> struct ConcurrentReadableHashMap {
702708 ElemTy *newElements = static_cast <ElemTy *>(malloc (newSize));
703709 if (elements) {
704710 memcpy (newElements, elements, elementCount * sizeof (ElemTy));
705- ElementFreeList. push_back ( elements);
711+ FreeListNode::add (&FreeList, elements);
706712 }
707713
708714 ElementCapacity = newCapacity;
@@ -739,7 +745,7 @@ template <class ElemTy> struct ConcurrentReadableHashMap {
739745
740746 Indices.store (newIndices, std::memory_order_release);
741747
742- IndicesFreeList. push_back ( indices);
748+ FreeListNode::add (&FreeList, indices);
743749
744750 return newIndices;
745751 }
@@ -792,7 +798,7 @@ template <class ElemTy> struct ConcurrentReadableHashMap {
792798 ~ConcurrentReadableHashMap () {
793799 assert (ReaderCount.load (std::memory_order_acquire) == 0 &&
794800 " deallocating ConcurrentReadableHashMap with outstanding snapshots" );
795- deallocateFreeList ( );
801+ FreeListNode::freeAll (&FreeList );
796802 }
797803
798804 // / Readers take a snapshot of the hash map, then work with the snapshot.
@@ -943,8 +949,8 @@ template <class ElemTy> struct ConcurrentReadableHashMap {
943949 Elements.store (nullptr , std::memory_order_relaxed);
944950 ElementCapacity = 0 ;
945951
946- IndicesFreeList. push_back ( indices);
947- ElementFreeList. push_back ( elements);
952+ FreeListNode::add (&FreeList, indices);
953+ FreeListNode::add (&FreeList, elements);
948954
949955 deallocateFreeListIfSafe ();
950956 }
0 commit comments