@@ -527,7 +527,12 @@ 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);
@@ -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