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:
1 parent
b3380b1f35
commit
576ac9ccfa
2 files changed
+21
-18
No files matched your search
@@ -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
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user