diff --git a/std/container/binaryheap.d b/std/container/binaryheap.d index 0fd34526ea7..ea3fcf71d2f 100644 --- a/std/container/binaryheap.d +++ b/std/container/binaryheap.d @@ -261,6 +261,26 @@ Clears the heap by detaching it from the underlying store. _payload = _payload.init; } +/** +Clears the inactive portion of the heap (from `length` to `capacity`) +to break GC reachability. This is useful for heaps with large capacities +where the unused portion might hold references to objects. + */ + void removeTail() + { + if (!_payload.refCountedStore.isInitialized) return; + if (_length >= _store.length) return; + alias T = typeof(_store[0]); + static if (hasIndirections!T) + { + // Clear the inactive portion of the store + foreach (i; _length .. _store.length) + { + _store[i] = T.init; + } + } + } + /** Inserts `value` into the store. If the underlying store is a range and $(D length == capacity), throws an exception. @@ -312,8 +332,8 @@ and $(D length == capacity), throws an exception. return 1; } -/** -Removes the largest element from the heap. + /** + Removes the largest element from the heap. */ void removeFront() { @@ -637,3 +657,24 @@ original Dyamic Array, but point to a new Dynamic Array. a[0] = 60; assert(h.front() == 40); } + +/// Test removeTail() clears inactive portion of heap with references +@system unittest +{ + class Node { int value; this(int v) { value = v; } } + + Node[] a = new Node[10]; + foreach (i; 0 .. 5) + a[i] = new Node(i); + + auto h = heapify!"a.value > b.value"(a[0 .. 5]); + + h.insert(new Node(6)); + Node saved = a[5]; + assert(a[6] is null); + + // After removeTail(), inactive slots should be cleared + h.removeTail(); + assert(a[5] is saved); // Active element unchanged + assert(a[6] is null); // Inactive slots cleared +}