@@ -527,13 +527,18 @@ template <class ElemTy> struct ConcurrentReadableArray {
527
527
528
528
storage = newStorage;
529
529
Capacity = newCapacity;
530
- Elements.store (storage, std::memory_order_release);
530
+
531
+ // Use seq_cst here to ensure that the subsequent load of ReaderCount is
532
+ // ordered after this store. If ReaderCount is loaded first, then a new
533
+ // reader could come in between that load and this store, and then we
534
+ // could end up freeing the old storage pointer while it's still in use.
535
+ Elements.store (storage, std::memory_order_seq_cst);
531
536
}
532
537
533
538
new (&storage->data ()[count]) ElemTy (elem);
534
539
storage->Count .store (count + 1 , std::memory_order_release);
535
540
536
- if (ReaderCount.load (std::memory_order_acquire ) == 0 )
541
+ if (ReaderCount.load (std::memory_order_seq_cst ) == 0 )
537
542
deallocateFreeList ();
538
543
}
539
544
@@ -848,7 +853,7 @@ struct ConcurrentReadableHashMap {
848
853
// / Free all the arrays in the free lists if there are no active readers. If
849
854
// / there are active readers, do nothing.
850
855
void deallocateFreeListIfSafe () {
851
- if (ReaderCount.load (std::memory_order_acquire ) == 0 )
856
+ if (ReaderCount.load (std::memory_order_seq_cst ) == 0 )
852
857
FreeListNode::freeAll (&FreeList);
853
858
}
854
859
@@ -866,7 +871,11 @@ struct ConcurrentReadableHashMap {
866
871
FreeListNode::add (&FreeList, elements);
867
872
}
868
873
869
- Elements.store (newElements, std::memory_order_release);
874
+ // Use seq_cst here to ensure that the subsequent load of ReaderCount is
875
+ // ordered after this store. If ReaderCount is loaded first, then a new
876
+ // reader could come in between that load and this store, and then we
877
+ // could end up freeing the old elements pointer while it's still in use.
878
+ Elements.store (newElements, std::memory_order_seq_cst);
870
879
return newElements;
871
880
}
872
881
@@ -900,7 +909,11 @@ struct ConcurrentReadableHashMap {
900
909
newIndices.storeIndexAt (nullptr , index, newI, std::memory_order_relaxed);
901
910
}
902
911
903
- Indices.store (newIndices.Value , std::memory_order_release);
912
+ // Use seq_cst here to ensure that the subsequent load of ReaderCount is
913
+ // ordered after this store. If ReaderCount is loaded first, then a new
914
+ // reader could come in between that load and this store, and then we
915
+ // could end up freeing the old indices pointer while it's still in use.
916
+ Indices.store (newIndices.Value , std::memory_order_seq_cst);
904
917
905
918
if (auto *ptr = indices.pointer ())
906
919
FreeListNode::add (&FreeList, ptr);
0 commit comments