From 4a1f2c1ffb541da5bdc4f0130c26829919efb72a Mon Sep 17 00:00:00 2001 From: mlemanczyk Date: Wed, 22 Mar 2023 00:00:41 +0100 Subject: [PATCH] Added rented array clearing if T is a reference type, as discussed in https://github.com/dotnet/runtime/issues/25378. --- Recyclable.Collections/RecyclableArrayList.cs | 6 ++++-- Recyclable.Collections/RecyclableList.cs | 17 ++++++++++------- .../RecyclableListExtensions.cs | 4 ++-- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/Recyclable.Collections/RecyclableArrayList.cs b/Recyclable.Collections/RecyclableArrayList.cs index d63bc23..561ac61 100644 --- a/Recyclable.Collections/RecyclableArrayList.cs +++ b/Recyclable.Collections/RecyclableArrayList.cs @@ -9,6 +9,8 @@ namespace Recyclable.Collections private static readonly ArrayPool _arrayPool = ArrayPool.Create(); private static readonly IEqualityComparer _equalityComparer = EqualityComparer.Default; + protected static readonly bool NeedsClearing = !typeof(T).IsValueType; + protected T[] _memoryBlock; private static void ThrowArgumentOutOfRangeException(in string message) @@ -32,7 +34,7 @@ namespace Recyclable.Collections sourceSpan.CopyTo(newArraySpan); if (sourceLength >= RecyclableDefaults.MinPooledArrayLength) { - arrayPool.Return(source!); + arrayPool.Return(source!, NeedsClearing); } } @@ -464,7 +466,7 @@ namespace Recyclable.Collections { Clear(); _capacity = 0; - _memoryBlock.ReturnToPool(_arrayPool); + _memoryBlock.ReturnToPool(_arrayPool, NeedsClearing); GC.SuppressFinalize(this); } } diff --git a/Recyclable.Collections/RecyclableList.cs b/Recyclable.Collections/RecyclableList.cs index aac2350..08cd2ef 100644 --- a/Recyclable.Collections/RecyclableList.cs +++ b/Recyclable.Collections/RecyclableList.cs @@ -5,7 +5,7 @@ using System.Runtime.CompilerServices; namespace Recyclable.Collections { public class RecyclableList : IDisposable, IList - { + { private const int ItemNotFoundIndex = -1; private const int BatchSize = 8; @@ -18,6 +18,9 @@ namespace Recyclable.Collections private int _blockSize; private int _lastBlockIndex; private int _nextItemIndex; + + protected static readonly bool NeedsClearing = !typeof(T).IsValueType; + protected ArrayPool _memoryBlocksPool; protected ArrayPool _blockArrayPool; protected T[][] _memoryBlocks; @@ -70,7 +73,7 @@ namespace Recyclable.Collections T[][] memoryBlocks = list._memoryBlocks; if (blockSize >= RecyclableDefaults.MinPooledArrayLength) { - blockArrayPool.Return(memoryBlocks[list.ReservedBlockCount - 1]); + blockArrayPool.Return(memoryBlocks[list.ReservedBlockCount - 1], NeedsClearing); } list._capacity -= blockSize; @@ -247,7 +250,7 @@ namespace Recyclable.Collections sourceSpan.CopyTo(newMemoryBlocksSpan); if (localInts[sourceBlockCount] >= RecyclableDefaults.MinPooledArrayLength) { - memoryBlocksPool.Return(source!); + memoryBlocksPool.Return(source!, NeedsClearing); } newMemoryBlocksSpan = newMemoryBlocksSpan[localInts[sourceBlockCount]..]; @@ -648,7 +651,7 @@ namespace Recyclable.Collections { if (items.Count >= RecyclableDefaults.MinPooledArrayLength) { - _blockArrayPool.Return(itemsBuffer); + _blockArrayPool.Return(itemsBuffer, NeedsClearing); } } } @@ -703,7 +706,7 @@ namespace Recyclable.Collections ArrayPool blockArrayPool = _blockArrayPool; for (int toRemoveIdx = 0; toRemoveIdx < memoryBlocksCount; toRemoveIdx++) { - blockArrayPool.Return(memoryBlocksSpan[toRemoveIdx]); + blockArrayPool.Return(memoryBlocksSpan[toRemoveIdx], NeedsClearing); } } @@ -777,7 +780,7 @@ namespace Recyclable.Collections } else { - _blockArrayPool.Return(_memoryBlocks[index]); + _blockArrayPool.Return(_memoryBlocks[index], NeedsClearing); } _capacity -= _blockSize; @@ -810,7 +813,7 @@ namespace Recyclable.Collections Clear(); if (_memoryBlocks.Length >= RecyclableDefaults.MinPooledArrayLength) { - _memoryBlocksPool.Return(_memoryBlocks); + _memoryBlocksPool.Return(_memoryBlocks, NeedsClearing); } GC.SuppressFinalize(this); diff --git a/Recyclable.Collections/RecyclableListExtensions.cs b/Recyclable.Collections/RecyclableListExtensions.cs index 4b51d43..f976537 100644 --- a/Recyclable.Collections/RecyclableListExtensions.cs +++ b/Recyclable.Collections/RecyclableListExtensions.cs @@ -155,11 +155,11 @@ namespace Recyclable.Collections : new T[minSize]; [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void ReturnToPool(this T[] array, ArrayPool arrayPool) + public static void ReturnToPool(this T[] array, ArrayPool arrayPool, bool needsClearing) { if (array.LongLength is > _minPooledArraySize and <= int.MaxValue) { - arrayPool.Return(array); + arrayPool.Return(array, needsClearing); } }