@@ -50,7 +50,7 @@ namespace snmalloc
5050 {
5151 auto next = get_next ();
5252
53- f (curr.get_capability ());
53+ f (curr.get_capability ());
5454
5555 curr = next;
5656 }
@@ -120,6 +120,12 @@ namespace snmalloc
120120 }
121121 };
122122
123+ /* *
124+ * This range slowly filters back memory to the parent range.
125+ * It locally caches memory and after it hasn't been used for some time
126+ * it goes back to its parent range.
127+ */
128+
123129 template <typename ParentRange, typename PAL, typename Pagemap>
124130 class DecayRange
125131 {
@@ -173,16 +179,21 @@ namespace snmalloc
173179
174180 static void handle_decay_tick ()
175181 {
176- auto new_epoch = (epoch + 1 ) % NUM_EPOCHS;
182+ static_assert (
183+ ParentRange::ConcurrencySafe,
184+ " Parent must be concurrency safe, as dealloc_range is called here on "
185+ " potentially another thread's state." );
186+ auto new_epoch =
187+ (epoch + 1 ) % NUM_EPOCHS;
177188 // Flush old index for all threads.
178189 auto curr = all_local.load (std::memory_order_acquire);
179190 while (curr != nullptr )
180191 {
181192 for (size_t sc = 0 ; sc < NUM_SLAB_SIZES; sc++)
182193 {
183194 auto old_stack = curr->chunk_stack [sc][new_epoch].pop_all ();
184-
185- old_stack.forall ([curr, sc](auto cap){
195+
196+ old_stack.forall ([curr, sc](auto cap) {
186197 curr->parent ->dealloc_range (cap, MIN_CHUNK_SIZE << sc);
187198 });
188199 }
@@ -228,6 +239,8 @@ namespace snmalloc
228239
229240 static constexpr bool Aligned = ParentRange::Aligned;
230241
242+ static constexpr bool ConcurrencySafe = false ;
243+
231244 constexpr DecayRange () = default;
232245
233246 capptr::Chunk<void > alloc_range (size_t size)
0 commit comments