RecyclableList.RemoveBlock renamed to ReleaseBlock.

RecyclableList.Clear will no longer create new arrays. It will only release the array to the pool & decrease capacity.

Fixed possibly infinite loop in Clear.
This commit is contained in:
mlemanczyk committed 2023-01-22 01:06:21 +01:00
1 parent b3380b1f35
commit 576ac9ccfa
2 files changed
+21 -18

No files matched your search

+20 -17
View File
@@ -43,9 +43,11 @@ namespace Recyclable.Collections
} }
list._longCount--; list._longCount--;
if (list._capacity - oldCountMinus1 == list._blockSize) int blockSize = list._blockSize;
if ((list._capacity * blockSize) - oldCountMinus1 == blockSize)
{ {
list.RemoveBlock(list._memoryBlocks.Length - 1); T[][] memoryBlocks = list._memoryBlocks;
ReleaseBlock(list, memoryBlocks, blockSize, memoryBlocks.Length - 1);
} }
} }
@@ -61,6 +63,11 @@ namespace Recyclable.Collections
ArrayPool<T> blockArrayPool = _blockArrayPool; ArrayPool<T> blockArrayPool = _blockArrayPool;
var sourceBlockCount = source?.Length ?? 0; var sourceBlockCount = source?.Length ?? 0;
int requiredBlockCount = (int)(newSize / blockSize) + (newSize % blockSize > 0 ? 1 : 0); int requiredBlockCount = (int)(newSize / blockSize) + (newSize % blockSize > 0 ? 1 : 0);
if (requiredBlockCount == sourceBlockCount)
{
return source!;
}
Span<T[]> newArraySpan; Span<T[]> newArraySpan;
T[][] newMemoryBlocks = requiredBlockCount.RentArrayFromPool(arrayPool); T[][] newMemoryBlocks = requiredBlockCount.RentArrayFromPool(arrayPool);
switch (requiredBlockCount >= sourceBlockCount) switch (requiredBlockCount >= sourceBlockCount)
@@ -123,8 +130,9 @@ namespace Recyclable.Collections
break; break;
} }
memory = SetNewLength(memory, _blockSize, newCapacity); int blockSize = _blockSize;
newCapacity = memory.Length; memory = SetNewLength(memory, blockSize, newCapacity);
newCapacity = memory.Length * blockSize;
_capacity = newCapacity; _capacity = newCapacity;
return newCapacity; return newCapacity;
} }
@@ -289,17 +297,20 @@ namespace Recyclable.Collections
try try
{ {
// Remove in reversed order for performance savings // Remove in reversed order for performance savings
while (_memoryBlocks.Length > 0) var toRemoveIdx = _memoryBlocks.Length - 1;
while (toRemoveIdx >= 0)
{ {
try try
{ {
_memoryBlocks = RemoveBlock(this, _memoryBlocks, _blockSize, _memoryBlocks.Length - 1); ReleaseBlock(this, _memoryBlocks, _blockSize, toRemoveIdx);
} }
catch (Exception) catch (Exception)
{ {
// We want to try returning as many arrays, as possible, before // We want to try returning as many arrays, as possible, before
// the list is cleared. // the list is cleared.
} }
toRemoveIdx--;
} }
} }
finally finally
@@ -318,25 +329,17 @@ namespace Recyclable.Collections
public void Insert(int index, T item) => throw new NotSupportedException(); public void Insert(int index, T item) => throw new NotSupportedException();
public long LongIndexOf(T item) => _memoryBlocks.LongIndexOf(_blockSize, item, _equalityComparer); public long LongIndexOf(T item) => _memoryBlocks.LongIndexOf(_blockSize, item, _equalityComparer);
public bool Remove(T item) => throw new NotSupportedException(); public bool Remove(T item) => throw new NotSupportedException();
public void RemoveBlock(int index) => _memoryBlocks = RemoveBlock(this, _memoryBlocks, _blockSize, index); public void RemoveBlock(int index) => ReleaseBlock(this, _memoryBlocks, _blockSize, index);
public void RemoveAt(int index) => RemoveAt(this, index); public void RemoveAt(int index) => RemoveAt(this, index);
public void RemoveAt(long index) => RemoveAt(this, index); public void RemoveAt(long index) => RemoveAt(this, index);
IEnumerator IEnumerable.GetEnumerator() => _memoryBlocks.Enumerate(_blockSize, LongCount).GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => _memoryBlocks.Enumerate(_blockSize, LongCount).GetEnumerator();
//private static void AddCapacity(RecyclableList<T> list, RecyclableArrayList<T[]> memoryBlocks, int additionalCapacity) private static void ReleaseBlock(RecyclableList<T> owner, in T[][] memoryBlocks, int blockSize, int blockIndex)
//{
// T[] newMemoryBlock = RentArrayFromPool(additionalCapacity);
// memoryBlocks.Add(newMemoryBlock);
// list.Capacity += additionalCapacity;
//}
private static T[][] RemoveBlock(RecyclableList<T> owner, in T[][] memoryBlocks, int blockSize, int blockIndex)
{ {
try try
{ {
var memoryBlocksSpan = new Span<T[]>(memoryBlocks); memoryBlocks[blockIndex].ReturnToPool(_blockArrayPool);
return SetNewLength(memoryBlocks, blockSize, memoryBlocks.Length - 1);
} }
finally finally
{ {
+1 -1
View File
@@ -47,7 +47,7 @@ namespace Recyclable.Collections
{ {
var toRemove = List[LongCount - 1]; var toRemove = List[LongCount - 1];
LongCount--; LongCount--;
if (List.Capacity * _blockSize - LongCount == _blockSize) if ((List.Capacity * _blockSize) - LongCount == _blockSize)
{ {
List.RemoveBlock(List.BlockCount - 1); List.RemoveBlock(List.BlockCount - 1);
} }