Added rented array clearing if T is a reference type, as discussed in https://github.com/dotnet/runtime/issues/25378.
This commit is contained in:
1 parent
d4af246a3a
commit
0f7237e3f0
4 files changed
+19
-12
No files matched your search
@@ -9,6 +9,8 @@ namespace Recyclable.Collections
|
|||||||
private static readonly ArrayPool<T> _arrayPool = ArrayPool<T>.Create();
|
private static readonly ArrayPool<T> _arrayPool = ArrayPool<T>.Create();
|
||||||
private static readonly IEqualityComparer<T> _equalityComparer = EqualityComparer<T>.Default;
|
private static readonly IEqualityComparer<T> _equalityComparer = EqualityComparer<T>.Default;
|
||||||
|
|
||||||
|
protected static readonly bool NeedsClearing = !typeof(T).IsValueType;
|
||||||
|
|
||||||
protected T[] _memoryBlock;
|
protected T[] _memoryBlock;
|
||||||
|
|
||||||
private static void ThrowArgumentOutOfRangeException(in string message)
|
private static void ThrowArgumentOutOfRangeException(in string message)
|
||||||
@@ -32,7 +34,7 @@ namespace Recyclable.Collections
|
|||||||
sourceSpan.CopyTo(newArraySpan);
|
sourceSpan.CopyTo(newArraySpan);
|
||||||
if (sourceLength >= RecyclableDefaults.MinPooledArrayLength)
|
if (sourceLength >= RecyclableDefaults.MinPooledArrayLength)
|
||||||
{
|
{
|
||||||
arrayPool.Return(source!);
|
arrayPool.Return(source!, NeedsClearing);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -464,7 +466,7 @@ namespace Recyclable.Collections
|
|||||||
{
|
{
|
||||||
Clear();
|
Clear();
|
||||||
_capacity = 0;
|
_capacity = 0;
|
||||||
_memoryBlock.ReturnToPool(_arrayPool);
|
_memoryBlock.ReturnToPool(_arrayPool, NeedsClearing);
|
||||||
GC.SuppressFinalize(this);
|
GC.SuppressFinalize(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ using System.Runtime.CompilerServices;
|
|||||||
namespace Recyclable.Collections
|
namespace Recyclable.Collections
|
||||||
{
|
{
|
||||||
public class RecyclableList<T> : IDisposable, IList<T>
|
public class RecyclableList<T> : IDisposable, IList<T>
|
||||||
{
|
{
|
||||||
private const int ItemNotFoundIndex = -1;
|
private const int ItemNotFoundIndex = -1;
|
||||||
private const int BatchSize = 8;
|
private const int BatchSize = 8;
|
||||||
|
|
||||||
@@ -18,6 +18,9 @@ namespace Recyclable.Collections
|
|||||||
private int _blockSize;
|
private int _blockSize;
|
||||||
private int _lastBlockIndex;
|
private int _lastBlockIndex;
|
||||||
private int _nextItemIndex;
|
private int _nextItemIndex;
|
||||||
|
|
||||||
|
protected static readonly bool NeedsClearing = !typeof(T).IsValueType;
|
||||||
|
|
||||||
protected ArrayPool<T[]> _memoryBlocksPool;
|
protected ArrayPool<T[]> _memoryBlocksPool;
|
||||||
protected ArrayPool<T> _blockArrayPool;
|
protected ArrayPool<T> _blockArrayPool;
|
||||||
protected T[][] _memoryBlocks;
|
protected T[][] _memoryBlocks;
|
||||||
@@ -70,7 +73,7 @@ namespace Recyclable.Collections
|
|||||||
T[][] memoryBlocks = list._memoryBlocks;
|
T[][] memoryBlocks = list._memoryBlocks;
|
||||||
if (blockSize >= RecyclableDefaults.MinPooledArrayLength)
|
if (blockSize >= RecyclableDefaults.MinPooledArrayLength)
|
||||||
{
|
{
|
||||||
blockArrayPool.Return(memoryBlocks[list.ReservedBlockCount - 1]);
|
blockArrayPool.Return(memoryBlocks[list.ReservedBlockCount - 1], NeedsClearing);
|
||||||
}
|
}
|
||||||
|
|
||||||
list._capacity -= blockSize;
|
list._capacity -= blockSize;
|
||||||
@@ -247,7 +250,7 @@ namespace Recyclable.Collections
|
|||||||
sourceSpan.CopyTo(newMemoryBlocksSpan);
|
sourceSpan.CopyTo(newMemoryBlocksSpan);
|
||||||
if (localInts[sourceBlockCount] >= RecyclableDefaults.MinPooledArrayLength)
|
if (localInts[sourceBlockCount] >= RecyclableDefaults.MinPooledArrayLength)
|
||||||
{
|
{
|
||||||
memoryBlocksPool.Return(source!);
|
memoryBlocksPool.Return(source!, NeedsClearing);
|
||||||
}
|
}
|
||||||
|
|
||||||
newMemoryBlocksSpan = newMemoryBlocksSpan[localInts[sourceBlockCount]..];
|
newMemoryBlocksSpan = newMemoryBlocksSpan[localInts[sourceBlockCount]..];
|
||||||
@@ -648,7 +651,7 @@ namespace Recyclable.Collections
|
|||||||
{
|
{
|
||||||
if (items.Count >= RecyclableDefaults.MinPooledArrayLength)
|
if (items.Count >= RecyclableDefaults.MinPooledArrayLength)
|
||||||
{
|
{
|
||||||
_blockArrayPool.Return(itemsBuffer);
|
_blockArrayPool.Return(itemsBuffer, NeedsClearing);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -703,7 +706,7 @@ namespace Recyclable.Collections
|
|||||||
ArrayPool<T> blockArrayPool = _blockArrayPool;
|
ArrayPool<T> blockArrayPool = _blockArrayPool;
|
||||||
for (int toRemoveIdx = 0; toRemoveIdx < memoryBlocksCount; toRemoveIdx++)
|
for (int toRemoveIdx = 0; toRemoveIdx < memoryBlocksCount; toRemoveIdx++)
|
||||||
{
|
{
|
||||||
blockArrayPool.Return(memoryBlocksSpan[toRemoveIdx]);
|
blockArrayPool.Return(memoryBlocksSpan[toRemoveIdx], NeedsClearing);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -777,7 +780,7 @@ namespace Recyclable.Collections
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_blockArrayPool.Return(_memoryBlocks[index]);
|
_blockArrayPool.Return(_memoryBlocks[index], NeedsClearing);
|
||||||
}
|
}
|
||||||
|
|
||||||
_capacity -= _blockSize;
|
_capacity -= _blockSize;
|
||||||
@@ -810,7 +813,7 @@ namespace Recyclable.Collections
|
|||||||
Clear();
|
Clear();
|
||||||
if (_memoryBlocks.Length >= RecyclableDefaults.MinPooledArrayLength)
|
if (_memoryBlocks.Length >= RecyclableDefaults.MinPooledArrayLength)
|
||||||
{
|
{
|
||||||
_memoryBlocksPool.Return(_memoryBlocks);
|
_memoryBlocksPool.Return(_memoryBlocks, NeedsClearing);
|
||||||
}
|
}
|
||||||
|
|
||||||
GC.SuppressFinalize(this);
|
GC.SuppressFinalize(this);
|
||||||
|
|||||||
@@ -155,11 +155,11 @@ namespace Recyclable.Collections
|
|||||||
: new T[minSize];
|
: new T[minSize];
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static void ReturnToPool<T>(this T[] array, ArrayPool<T> arrayPool)
|
public static void ReturnToPool<T>(this T[] array, ArrayPool<T> arrayPool, bool needsClearing)
|
||||||
{
|
{
|
||||||
if (array.LongLength is > _minPooledArraySize and <= int.MaxValue)
|
if (array.LongLength is > _minPooledArraySize and <= int.MaxValue)
|
||||||
{
|
{
|
||||||
arrayPool.Return(array);
|
arrayPool.Return(array, needsClearing);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,6 +45,8 @@ namespace Recyclable.Collections
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected static readonly bool NeedsClearing = !typeof(T).IsValueType;
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
protected static long GetAbsoluteIndex(long index, long removedCount) => index + removedCount;
|
protected static long GetAbsoluteIndex(long index, long removedCount) => index + removedCount;
|
||||||
|
|
||||||
@@ -181,7 +183,7 @@ namespace Recyclable.Collections
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Memory[index].ReturnToPool(_arrayPool);
|
Memory[index].ReturnToPool(_arrayPool, NeedsClearing);
|
||||||
Memory.RemoveAt(index);
|
Memory.RemoveAt(index);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
|
|||||||
Reference in new issue
Block a user