Cleanup. RecyclableList static methods moved to RecyclableList.Helpers.

This commit is contained in:
mlemanczyk committed 2023-06-29 13:35:12 +02:00
1 parent c7e23f5f3c
commit ba0d15cdcb
2 files changed
+71 -63

No files matched your search

@@ -1,4 +1,5 @@
using System.Runtime.CompilerServices; using System.Buffers;
using System.Runtime.CompilerServices;
namespace Recyclable.Collections namespace Recyclable.Collections
{ {
@@ -50,6 +51,32 @@ namespace Recyclable.Collections
} }
} }
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public static int EnsureCapacity(RecyclableList<T> list, int requestedCapacity)
{
int newCapacity;
switch (list._capacity > 0)
{
case true:
newCapacity = list._capacity;
while (newCapacity < requestedCapacity)
{
newCapacity <<= 1;
}
break;
case false:
newCapacity = requestedCapacity;
break;
}
list._memoryBlock = Resize(list._memoryBlock, newCapacity);
newCapacity = list._memoryBlock.Length;
list._capacity = newCapacity;
return newCapacity;
}
[Obsolete("This method WILL be removed in the near future. Please use the existing enumerators instead of it.")] [Obsolete("This method WILL be removed in the near future. Please use the existing enumerators instead of it.")]
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static IEnumerable<T> Enumerate(RecyclableList<T[]> arrays, int chunkSize, long totalCount) public static IEnumerable<T> Enumerate(RecyclableList<T[]> arrays, int chunkSize, long totalCount)
@@ -211,6 +238,33 @@ namespace Recyclable.Collections
return values[middle]; return values[middle];
} }
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public static T[] Resize(in T[]? source, int newSize)
{
ArrayPool<T> arrayPool = _arrayPool;
T[] newMemoryBlock = newSize >= RecyclableDefaults.MinPooledArrayLength
? arrayPool.Rent(newSize)
: new T[newSize];
if (source?.Length > 0)
{
Array.Copy(source!, 0, newMemoryBlock, 0, source!.Length);
if (source!.Length >= RecyclableDefaults.MinPooledArrayLength)
{
// TODO: Measure gain vs relying on arrayPool to clear
//if (NeedsClearing)
//{
// Array.Clear(source);
//}
// If anything, it has been already cleared above, so we don't need to repeat it.
arrayPool.Return(source, NeedsClearing);
}
}
return newMemoryBlock;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private static void Swap(IList<T> values, int xIndex, int yIndex) private static void Swap(IList<T> values, int xIndex, int yIndex)
=> (values[yIndex], values[xIndex]) = (values[xIndex], values[yIndex]); => (values[yIndex], values[xIndex]) = (values[xIndex], values[yIndex]);
+16 -62
View File
@@ -13,10 +13,10 @@ namespace Recyclable.Collections
public static explicit operator ReadOnlySpan<T>(RecyclableList<T> source) => new(source._memoryBlock, 0, source.Count); public static explicit operator ReadOnlySpan<T>(RecyclableList<T> source) => new(source._memoryBlock, 0, source.Count);
#nullable disable #nullable disable
private T[] _memoryBlock; internal T[] _memoryBlock;
#nullable restore #nullable restore
private ulong _version; internal ulong _version;
public ulong Version => _version; public ulong Version => _version;
private IEnumerator<T> AddRangeEnumerated(IEnumerable<T> source, int growByCount) private IEnumerator<T> AddRangeEnumerated(IEnumerable<T> source, int growByCount)
@@ -36,7 +36,7 @@ namespace Recyclable.Collections
{ {
if (targetItemIdx + growByCount > capacity) if (targetItemIdx + growByCount > capacity)
{ {
capacity = EnsureCapacity(this, capacity + growByCount); capacity = Helpers.EnsureCapacity(this, capacity + growByCount);
memorySpan = new(_memoryBlock); memorySpan = new(_memoryBlock);
available = capacity - targetItemIdx; available = capacity - targetItemIdx;
} }
@@ -59,7 +59,7 @@ namespace Recyclable.Collections
private void AddRangeWithKnownCount(IEnumerable<T> source, int targetItemIdx, int requiredAdditionalCapacity) private void AddRangeWithKnownCount(IEnumerable<T> source, int targetItemIdx, int requiredAdditionalCapacity)
{ {
_ = EnsureCapacity(this, targetItemIdx + requiredAdditionalCapacity); _ = Helpers.EnsureCapacity(this, targetItemIdx + requiredAdditionalCapacity);
Span<T> memorySpan = new(_memoryBlock); Span<T> memorySpan = new(_memoryBlock);
foreach (var item in source) foreach (var item in source)
@@ -70,52 +70,6 @@ namespace Recyclable.Collections
_count = targetItemIdx; _count = targetItemIdx;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
private static T[] Resize(in T[]? source, int newSize)
{
ArrayPool<T> arrayPool = _arrayPool;
T[] newMemoryBlock = newSize >= RecyclableDefaults.MinPooledArrayLength
? arrayPool.Rent(newSize)
: new T[newSize];
if (source?.Length > 0)
{
Array.Copy(source!, 0, newMemoryBlock, 0, source!.Length);
if (source!.Length >= RecyclableDefaults.MinPooledArrayLength)
{
arrayPool.Return(source!, NeedsClearing);
}
}
return newMemoryBlock;
}
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
private static int EnsureCapacity(RecyclableList<T> list, int requestedCapacity)
{
int newCapacity;
switch (list._capacity > 0)
{
case true:
newCapacity = list._capacity;
while (newCapacity < requestedCapacity)
{
newCapacity <<= 1;
}
break;
case false:
newCapacity = requestedCapacity;
break;
}
list._memoryBlock = Resize(list._memoryBlock, newCapacity);
newCapacity = list._memoryBlock.Length;
list._capacity = newCapacity;
return newCapacity;
}
#pragma warning disable CS8618 // _memory will be initialized when the 1st item is added #pragma warning disable CS8618 // _memory will be initialized when the 1st item is added
public RecyclableList() public RecyclableList()
#pragma warning restore CS8618 #pragma warning restore CS8618
@@ -128,7 +82,7 @@ namespace Recyclable.Collections
{ {
if (initialCapacity > 0) if (initialCapacity > 0)
{ {
_memoryBlock = Resize(_memoryBlock, initialCapacity); _memoryBlock = Helpers.Resize(_memoryBlock, initialCapacity);
_capacity = _memoryBlock.Length; _capacity = _memoryBlock.Length;
} }
} }
@@ -177,7 +131,7 @@ namespace Recyclable.Collections
public RecyclableList(IEnumerable<T> source, int initialCapacity = RecyclableDefaults.Capacity) public RecyclableList(IEnumerable<T> source, int initialCapacity = RecyclableDefaults.Capacity)
{ {
_memoryBlock = Resize(_memoryBlock, initialCapacity); _memoryBlock = Helpers.Resize(_memoryBlock, initialCapacity);
_capacity = _memoryBlock.Length; _capacity = _memoryBlock.Length;
AddRange(source); AddRange(source);
} }
@@ -203,14 +157,14 @@ namespace Recyclable.Collections
{ {
if (_capacity != value) if (_capacity != value)
{ {
_memoryBlock = Resize(_memoryBlock, value); _memoryBlock = Helpers.Resize(_memoryBlock, value);
_capacity = _memoryBlock.Length; _capacity = _memoryBlock.Length;
_version++; _version++;
} }
} }
} }
private int _count; internal int _count;
public int Count => _count; public int Count => _count;
public bool IsReadOnly => false; public bool IsReadOnly => false;
@@ -221,7 +175,7 @@ namespace Recyclable.Collections
int requiredCapacity = _count + 1; int requiredCapacity = _count + 1;
if (_capacity < requiredCapacity) if (_capacity < requiredCapacity)
{ {
_ = EnsureCapacity(this, requiredCapacity); _ = Helpers.EnsureCapacity(this, requiredCapacity);
} }
_memoryBlock[_count++] = item; _memoryBlock[_count++] = item;
@@ -240,7 +194,7 @@ namespace Recyclable.Collections
int targetCapacity = _count + sourceItemsCount; int targetCapacity = _count + sourceItemsCount;
if (_capacity < targetCapacity) if (_capacity < targetCapacity)
{ {
_ = EnsureCapacity(this, targetCapacity); _ = Helpers.EnsureCapacity(this, targetCapacity);
} }
var targetSpan = new Span<T>(_memoryBlock, _count, sourceItemsCount); var targetSpan = new Span<T>(_memoryBlock, _count, sourceItemsCount);
@@ -263,7 +217,7 @@ namespace Recyclable.Collections
int targetCapacity = _count + sourceItemsCount; int targetCapacity = _count + sourceItemsCount;
if (_capacity < targetCapacity) if (_capacity < targetCapacity)
{ {
_ = EnsureCapacity(this, targetCapacity); _ = Helpers.EnsureCapacity(this, targetCapacity);
} }
var targetSpan = new Span<T>(_memoryBlock, _count, sourceItemsCount); var targetSpan = new Span<T>(_memoryBlock, _count, sourceItemsCount);
@@ -285,7 +239,7 @@ namespace Recyclable.Collections
var targetCapacity = _count + sourceItemsCount; var targetCapacity = _count + sourceItemsCount;
if (_capacity < targetCapacity) if (_capacity < targetCapacity)
{ {
_ = EnsureCapacity(this, targetCapacity); _ = Helpers.EnsureCapacity(this, targetCapacity);
} }
items.CopyTo(_memoryBlock, _count); items.CopyTo(_memoryBlock, _count);
@@ -306,7 +260,7 @@ namespace Recyclable.Collections
var targetCapacity = _count + sourceItemsCount; var targetCapacity = _count + sourceItemsCount;
if (_capacity < targetCapacity) if (_capacity < targetCapacity)
{ {
_ = EnsureCapacity(this, targetCapacity); _ = Helpers.EnsureCapacity(this, targetCapacity);
} }
items.CopyTo(_memoryBlock, _count); items.CopyTo(_memoryBlock, _count);
@@ -327,7 +281,7 @@ namespace Recyclable.Collections
var targetCapacity = _count + sourceItemsCount; var targetCapacity = _count + sourceItemsCount;
if (_capacity < targetCapacity) if (_capacity < targetCapacity)
{ {
_ = EnsureCapacity(this, targetCapacity); _ = Helpers.EnsureCapacity(this, targetCapacity);
} }
var targetSpan = new Span<T>(_memoryBlock, _count, sourceItemsCount); var targetSpan = new Span<T>(_memoryBlock, _count, sourceItemsCount);
@@ -360,7 +314,7 @@ namespace Recyclable.Collections
int targetCapacity = _count + (int)sourceItemsCount; int targetCapacity = _count + (int)sourceItemsCount;
if (_capacity < targetCapacity) if (_capacity < targetCapacity)
{ {
_ = EnsureCapacity(this, targetCapacity); _ = Helpers.EnsureCapacity(this, targetCapacity);
} }
Span<T> targetSpan = new Span<T>(_memoryBlock)[_count..], Span<T> targetSpan = new Span<T>(_memoryBlock)[_count..],
@@ -461,7 +415,7 @@ namespace Recyclable.Collections
int requestedCapacity = oldCount + 1; int requestedCapacity = oldCount + 1;
if (_capacity < requestedCapacity) if (_capacity < requestedCapacity)
{ {
_ = EnsureCapacity(this, requestedCapacity); _ = Helpers.EnsureCapacity(this, requestedCapacity);
} }
if (oldCount > 0) if (oldCount > 0)