From 9d9a8abd7659f40011b7599e803d9f9cf647d37c Mon Sep 17 00:00:00 2001 From: mlemanczyk Date: Sat, 1 Jul 2023 14:13:02 +0200 Subject: [PATCH] Cleanup. RecyclableLongList static methods moved to RecyclableLongList.Helpers. --- .../RecyclableLongList.Helpers.cs | 190 +++++++++++- .../RecyclableLongList.IList.cs | 8 +- Recyclable.Collections/RecyclableLongList.cs | 278 +++--------------- 3 files changed, 241 insertions(+), 235 deletions(-) diff --git a/Recyclable.Collections/RecyclableLongList.Helpers.cs b/Recyclable.Collections/RecyclableLongList.Helpers.cs index 823053f..b098f18 100644 --- a/Recyclable.Collections/RecyclableLongList.Helpers.cs +++ b/Recyclable.Collections/RecyclableLongList.Helpers.cs @@ -1,9 +1,60 @@ -namespace Recyclable.Collections +using Recyclable.Collections.Pools; +using System.Buffers; +using System.Numerics; +using System.Runtime.CompilerServices; + +namespace Recyclable.Collections { public partial class RecyclableLongList { internal static class Helpers { + [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)] + public static void CopyFollowingItems(RecyclableLongList list, long destinationItemIndex) + { + T[][] memoryBlocks = list._memoryBlocks; + int nextItemIndex = list._nextItemIndex; + int blockSize = list._blockSize; + int sourceBlockIndex = (int)((destinationItemIndex + 1) >> list._blockSizePow2BitShift); + int sourceItemIndex = (int)((destinationItemIndex + 1) & list._blockSizeMinus1); + + int targetBlockIndex = (int)(destinationItemIndex >> list._blockSizePow2BitShift); + int targetItemIndex = (int)(destinationItemIndex & list._blockSizeMinus1); + + int lastTakenBlockIndex = list._lastBlockWithData; + while (sourceBlockIndex < lastTakenBlockIndex || (sourceBlockIndex == lastTakenBlockIndex && (sourceItemIndex < nextItemIndex || sourceBlockIndex != list._nextItemBlockIndex))) + { + int toCopy = sourceBlockIndex < lastTakenBlockIndex || nextItemIndex == 0 + ? blockSize - (sourceItemIndex >= targetItemIndex ? sourceItemIndex : targetItemIndex) + : Math.Min(nextItemIndex, blockSize - targetItemIndex); + + Array.Copy(memoryBlocks[sourceBlockIndex], sourceItemIndex, memoryBlocks[targetBlockIndex], targetItemIndex, toCopy); + + // We didn't have enough room in the target array block. There are still items in the source array block to copy. + if (sourceItemIndex + toCopy < blockSize) + { + sourceItemIndex += toCopy; + targetBlockIndex++; + targetItemIndex = 0; + } + // We copied all the source items in the current array block. But have we filled the target? + else + { + sourceItemIndex = 0; + sourceBlockIndex++; + if (targetItemIndex + toCopy < blockSize) + { + targetItemIndex += toCopy; + } + else + { + targetBlockIndex++; + targetItemIndex = 0; + } + } + } + } + public static void CopyTo(T[][] sourceMemoryBlocks, long startingIndex, int blockSize, long itemsCount, T[] destinationArray, int destinationArrayIndex) { if (itemsCount <= 0) @@ -56,6 +107,25 @@ } } + [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)] + public static long EnsureCapacity(RecyclableLongList list, long requestedCapacity) + { + long newCapacity = list._capacity > 0 + ? checked((long)BitOperations.RoundUpToPowerOf2((ulong)requestedCapacity)) + : requestedCapacity; + + int blockSize = list._blockSize; + newCapacity = Resize(list, blockSize, list._blockSizePow2BitShift, newCapacity); + if (blockSize != list._memoryBlocks[0].Length && newCapacity > 0) + { + SetupBlockArrayPooling(list, list._memoryBlocks[0].Length); + list._blockSizeMinus1 = list._blockSize - 1; + } + + list._capacity = newCapacity; + return newCapacity; + } + public static IEnumerable Enumerate(T[][] arrays, int chunkSize, long totalCount) { long currentCount = 0; @@ -85,6 +155,124 @@ } } } + + [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)] + private static int GetEstimatedBlockSize(int minBlockSize, ArrayPool blockArrayPool) + { + var array = blockArrayPool.Rent(minBlockSize); + minBlockSize = array.Length; + blockArrayPool.Return(array); + return minBlockSize; + } + + /// + /// Creates a set of new memory buffers, if needed, to allow storing at minimum no. of items. + /// + /// that needs to be resized. + /// Minimal requested block size. It MUST be rounded to the power of 2, see remarks. + /// Pre-calculated bit shifting value for left & right shift operations against. + /// The minimum no. of items MUST be able to store after . + /// + /// For performance reasons, MUST a power of 2. This simplifies a lot block & item + /// index calculations, i.e. makes them logical operations on bits. + /// + /// This method checks for integral overflow. + /// + /// + /// This method doesn't support downsizing the memory block. As such it doesn't release excessive blocks. This is to for additional performance + /// gain - 1+ operation less for each call. If you need this functionality, you need to implement it on a higher level. + /// + /// The maximum no. of items can store. + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] + public static long Resize(RecyclableLongList list, int minBlockSize, byte minBlockSizePow2Shift, long newCapacity) + { + ArrayPool blockArrayPool = list._blockArrayPool; + int sourceBlockCount = list._reservedBlockCount; + int requiredBlockCount = checked((int)(newCapacity >> minBlockSizePow2Shift) + ((newCapacity & (minBlockSize - 1)) > 0 ? 1 : 0)); + int blockIndex; + + T[][] newMemoryBlocks; + if (requiredBlockCount > (list._memoryBlocks?.Length ?? 0)) + { + // Allocate new memory block for all arrays + newMemoryBlocks = requiredBlockCount >= RecyclableDefaults.MinPooledArrayLength ? list._memoryBlocksPool.Rent(requiredBlockCount) : new T[requiredBlockCount][]; + + // Copy arrays from the old memory block for all arrays + if (sourceBlockCount > 0) + { + Array.Copy(list._memoryBlocks!, newMemoryBlocks, sourceBlockCount); + // We can now return the old memory block for all arrays itself + if (sourceBlockCount >= RecyclableDefaults.MinPooledArrayLength) + { + list._memoryBlocksPool.Return(list._memoryBlocks!, NeedsClearing); + } + } + + list._memoryBlocks = newMemoryBlocks; + } + else + { + newMemoryBlocks = list._memoryBlocks!; + } + + // Allocate arrays for any new blocks + if (requiredBlockCount > sourceBlockCount) + { + if (minBlockSize >= RecyclableDefaults.MinPooledArrayLength) + { + if (sourceBlockCount == 0) + { + minBlockSize = GetEstimatedBlockSize(minBlockSize, blockArrayPool); + } + + blockIndex = sourceBlockCount; + while (true) + { + newMemoryBlocks[blockIndex] = blockArrayPool.Rent(minBlockSize); + if (blockIndex + 1 < requiredBlockCount) + { + blockIndex++; + } + else + { + break; + } + } + } + else + { + blockIndex = sourceBlockCount; + while (true) + { + newMemoryBlocks[blockIndex] = new T[minBlockSize]; + if (blockIndex + 1 < requiredBlockCount) + { + blockIndex++; + } + else + { + break; + } + } + } + } + + list._reservedBlockCount = requiredBlockCount; + return (long)requiredBlockCount << minBlockSizePow2Shift; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] + public static void SetupBlockArrayPooling(RecyclableLongList list, int blockSize, ArrayPool? blockArrayPool = null) + { + list._blockSize = blockSize; + list._blockSizePow2BitShift = (byte)(31 - BitOperations.LeadingZeroCount((uint)blockSize)); + list._blockArrayPool = blockSize >= RecyclableDefaults.MinPooledArrayLength + ? blockArrayPool ?? RecyclableArrayPool.Shared(blockSize) + : RecyclableArrayPool.Null; + } + + public static void ThrowIndexOutOfRangeException(in string message) => throw new ArgumentOutOfRangeException("index", message); + public static void ThrowArgumentOutOfRangeException(in string argumentName, in string message) => throw new ArgumentOutOfRangeException(argumentName, message); } } } diff --git a/Recyclable.Collections/RecyclableLongList.IList.cs b/Recyclable.Collections/RecyclableLongList.IList.cs index 057fcdf..befd6bf 100644 --- a/Recyclable.Collections/RecyclableLongList.IList.cs +++ b/Recyclable.Collections/RecyclableLongList.IList.cs @@ -39,7 +39,7 @@ namespace Recyclable.Collections } else { - ThrowArgumentOutOfRangeException(nameof(value), $"Argument is invalid. {(value != null ? "List element type is incompatible with the given value" : "Element is null and the list doesn't allow null values.")}"); + Helpers.ThrowArgumentOutOfRangeException(nameof(value), $"Argument is invalid. {(value != null ? "List element type is incompatible with the given value" : "Element is null and the list doesn't allow null values.")}"); } } } @@ -58,7 +58,7 @@ namespace Recyclable.Collections } else { - ThrowArgumentOutOfRangeException(nameof(value), $"Argument is invalid. {(value != null ? "List element type is incompatible with the given value" : "Element is null and the list doesn't allow null values.")}"); + Helpers.ThrowArgumentOutOfRangeException(nameof(value), $"Argument is invalid. {(value != null ? "List element type is incompatible with the given value" : "Element is null and the list doesn't allow null values.")}"); return RecyclableDefaults.ItemNotFoundIndex; } } @@ -91,7 +91,7 @@ namespace Recyclable.Collections } else { - ThrowArgumentOutOfRangeException(nameof(value), $"Argument is invalid. {(value != null ? "List element type is incompatible with the given value" : "Element is null and the list doesn't allow null values.")}"); + Helpers.ThrowArgumentOutOfRangeException(nameof(value), $"Argument is invalid. {(value != null ? "List element type is incompatible with the given value" : "Element is null and the list doesn't allow null values.")}"); } } @@ -109,7 +109,7 @@ namespace Recyclable.Collections } else { - ThrowArgumentOutOfRangeException(nameof(value), $"Argument is invalid. {(value != null ? "List element type is incompatible with the given value" : "Element is null and the list doesn't allow null values.")}"); + Helpers.ThrowArgumentOutOfRangeException(nameof(value), $"Argument is invalid. {(value != null ? "List element type is incompatible with the given value" : "Element is null and the list doesn't allow null values.")}"); } } diff --git a/Recyclable.Collections/RecyclableLongList.cs b/Recyclable.Collections/RecyclableLongList.cs index 377ec46..6b54e2d 100644 --- a/Recyclable.Collections/RecyclableLongList.cs +++ b/Recyclable.Collections/RecyclableLongList.cs @@ -15,8 +15,6 @@ namespace Recyclable.Collections private static readonly T[][] _emptyMemoryBlocksArray = new T[0][]; private static readonly T[] _emptyBlockArray = new T[0]; private static readonly bool _defaultIsNull = default(T) == null; - private static void ThrowIndexOutOfRangeException(in string message) => throw new ArgumentOutOfRangeException("index", message); - private static void ThrowArgumentOutOfRangeException(in string argumentName, in string message) => throw new ArgumentOutOfRangeException(argumentName, message); internal int _blockSize; internal byte _blockSizePow2BitShift; @@ -43,7 +41,7 @@ namespace Recyclable.Collections _version++; if (_capacity != value) { - _capacity = Resize(this, _blockSize, _blockSizePow2BitShift, value); + _capacity = Helpers.Resize(this, _blockSize, _blockSizePow2BitShift, value); _version++; } } @@ -64,55 +62,9 @@ namespace Recyclable.Collections public int NextItemBlockIndex => _nextItemBlockIndex; public int NextItemIndex => _nextItemIndex; - private ulong _version; + internal ulong _version; public ulong Version => _version; - [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)] - private static void CopyFollowingItems(RecyclableLongList list, long destinationItemIndex) - { - T[][] memoryBlocks = list._memoryBlocks; - int nextItemIndex = list._nextItemIndex; - int blockSize = list._blockSize; - int sourceBlockIndex = (int)((destinationItemIndex + 1) >> list._blockSizePow2BitShift); - int sourceItemIndex = (int)((destinationItemIndex + 1) & list._blockSizeMinus1); - - int targetBlockIndex = (int)(destinationItemIndex >> list._blockSizePow2BitShift); - int targetItemIndex = (int)(destinationItemIndex & list._blockSizeMinus1); - - int lastTakenBlockIndex = list._lastBlockWithData; - while (sourceBlockIndex < lastTakenBlockIndex || (sourceBlockIndex == lastTakenBlockIndex && (sourceItemIndex < nextItemIndex || sourceBlockIndex != list._nextItemBlockIndex))) - { - int toCopy = sourceBlockIndex < lastTakenBlockIndex || nextItemIndex == 0 - ? blockSize - (sourceItemIndex >= targetItemIndex ? sourceItemIndex : targetItemIndex) - : Math.Min(nextItemIndex, blockSize - targetItemIndex); - - Array.Copy(memoryBlocks[sourceBlockIndex], sourceItemIndex, memoryBlocks[targetBlockIndex], targetItemIndex, toCopy); - - // We didn't have enough room in the target array block. There are still items in the source array block to copy. - if (sourceItemIndex + toCopy < blockSize) - { - sourceItemIndex += toCopy; - targetBlockIndex++; - targetItemIndex = 0; - } - // We copied all the source items in the current array block. But have we filled the target? - else - { - sourceItemIndex = 0; - sourceBlockIndex++; - if (targetItemIndex + toCopy < blockSize) - { - targetItemIndex += toCopy; - } - else - { - targetBlockIndex++; - targetItemIndex = 0; - } - } - } - } - private void AddRangeEnumerated(IEnumerable source, int growByCount) { long i, copied = _longCount; @@ -134,7 +86,7 @@ namespace Recyclable.Collections { if (copied + growByCount > capacity) { - capacity = EnsureCapacity(this, capacity + growByCount); + capacity = Helpers.EnsureCapacity(this, capacity + growByCount); memoryBlocksCount = _reservedBlockCount; if (blockSize != _blockSize) { @@ -198,7 +150,7 @@ namespace Recyclable.Collections long requiredCapacity = copied + requiredAdditionalCapacity; if (_capacity < requiredCapacity) { - _ = EnsureCapacity(this, requiredCapacity); + _ = Helpers.EnsureCapacity(this, requiredCapacity); blockSize = _blockSize; } @@ -227,140 +179,6 @@ namespace Recyclable.Collections _lastBlockWithData = targetBlockIdx - (targetItemIdx > 0 ? 0 : 1); } - /// - /// Creates a set of new memory buffers, if needed, to allow storing at minimum no. of items. - /// - /// that needs to be resized. - /// Minimal requested block size. It MUST be rounded to the power of 2, see remarks. - /// Pre-calculated bit shifting value for left & right shift operations against. - /// The minimum no. of items MUST be able to store after . - /// - /// For performance reasons, MUST a power of 2. This simplifies a lot block & item - /// index calculations, i.e. makes them logical operations on bits. - /// - /// This method checks for integral overflow. - /// - /// - /// This method doesn't support downsizing the memory block. As such it doesn't release excessive blocks. This is to for additional performance - /// gain - 1+ operation less for each call. If you need this functionality, you need to implement it on a higher level. - /// - /// The maximum no. of items can store. - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static long Resize(RecyclableLongList list, int minBlockSize, byte minBlockSizePow2Shift, long newCapacity) - { - ArrayPool blockArrayPool = list._blockArrayPool; - int sourceBlockCount = list._reservedBlockCount; - int requiredBlockCount = checked((int)(newCapacity >> minBlockSizePow2Shift) + ((newCapacity & (minBlockSize - 1)) > 0 ? 1 : 0)); - int blockIndex; - - T[][] newMemoryBlocks; - if (requiredBlockCount > (list._memoryBlocks?.Length ?? 0)) - { - // Allocate new memory block for all arrays - newMemoryBlocks = requiredBlockCount >= RecyclableDefaults.MinPooledArrayLength ? list._memoryBlocksPool.Rent(requiredBlockCount) : new T[requiredBlockCount][]; - - // Copy arrays from the old memory block for all arrays - if (sourceBlockCount > 0) - { - Array.Copy(list._memoryBlocks!, newMemoryBlocks, sourceBlockCount); - // We can now return the old memory block for all arrays itself - if (sourceBlockCount >= RecyclableDefaults.MinPooledArrayLength) - { - list._memoryBlocksPool.Return(list._memoryBlocks!, true); - } - } - - list._memoryBlocks = newMemoryBlocks; - } - else - { - newMemoryBlocks = list._memoryBlocks!; - } - - // Allocate arrays for any new blocks - if (requiredBlockCount > sourceBlockCount) - { - if (minBlockSize >= RecyclableDefaults.MinPooledArrayLength) - { - if (sourceBlockCount == 0) - { - minBlockSize = GetEstimatedBlockSize(minBlockSize, blockArrayPool); - } - - blockIndex = sourceBlockCount; - while (true) - { - newMemoryBlocks[blockIndex] = blockArrayPool.Rent(minBlockSize); - if (blockIndex + 1 < requiredBlockCount) - { - blockIndex++; - } - else - { - break; - } - } - } - else - { - blockIndex = sourceBlockCount; - while (true) - { - newMemoryBlocks[blockIndex] = new T[minBlockSize]; - if (blockIndex + 1 < requiredBlockCount) - { - blockIndex++; - } - else - { - break; - } - } - } - } - - list._reservedBlockCount = requiredBlockCount; - return (long)requiredBlockCount << minBlockSizePow2Shift; - } - - [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)] - private static int GetEstimatedBlockSize(int minBlockSize, ArrayPool blockArrayPool) - { - var array = blockArrayPool.Rent(minBlockSize); - minBlockSize = array.Length; - blockArrayPool.Return(array); - return minBlockSize; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private static void SetupBlockArrayPooling(RecyclableLongList list, int blockSize, ArrayPool? blockArrayPool = null) - { - list._blockSize = blockSize; - list._blockSizePow2BitShift = (byte)(31 - BitOperations.LeadingZeroCount((uint)blockSize)); - list._blockArrayPool = blockSize >= RecyclableDefaults.MinPooledArrayLength - ? blockArrayPool ?? RecyclableArrayPool.Shared(blockSize) - : RecyclableArrayPool.Null; - } - - [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)] - private static long EnsureCapacity(RecyclableLongList list, long requestedCapacity) - { - long newCapacity = list._capacity > 0 - ? checked((long)BitOperations.RoundUpToPowerOf2((ulong)requestedCapacity)) - : requestedCapacity; - - int blockSize = list._blockSize; - newCapacity = Resize(list, blockSize, list._blockSizePow2BitShift, newCapacity); - if (blockSize != list._memoryBlocks[0].Length && newCapacity > 0) - { - SetupBlockArrayPooling(list, list._memoryBlocks[0].Length); - list._blockSizeMinus1 = list._blockSize - 1; - } - - list._capacity = newCapacity; - return newCapacity; - } - [MethodImpl(MethodImplOptions.AggressiveOptimization)] #pragma warning disable CS8618 // The reported properties / fields are set by SetupBlockArrayPooling public RecyclableLongList(int minBlockSize = RecyclableDefaults.BlockSize, long? expectedItemsCount = default, ArrayPool? memoryBlocksPool = default, ArrayPool? blockArrayPool = default) @@ -371,11 +189,11 @@ namespace Recyclable.Collections if (expectedItemsCount > 0) { minBlockSize = checked((int)BitOperations.RoundUpToPowerOf2((uint)minBlockSize)); - SetupBlockArrayPooling(this, minBlockSize, blockArrayPool); - _capacity = Resize(this, minBlockSize, _blockSizePow2BitShift, expectedItemsCount.Value); + Helpers.SetupBlockArrayPooling(this, minBlockSize, blockArrayPool); + _capacity = Helpers.Resize(this, minBlockSize, _blockSizePow2BitShift, expectedItemsCount.Value); if (_blockSize != _memoryBlocks![0].Length && _capacity > 0) { - SetupBlockArrayPooling(this, _memoryBlocks[0].Length, blockArrayPool); + Helpers.SetupBlockArrayPooling(this, _memoryBlocks[0].Length, blockArrayPool); _blockSizeMinus1 = _blockSize - 1; } else @@ -385,7 +203,7 @@ namespace Recyclable.Collections } else { - SetupBlockArrayPooling(this, checked((int)BitOperations.RoundUpToPowerOf2((uint)minBlockSize)), blockArrayPool); + Helpers.SetupBlockArrayPooling(this, checked((int)BitOperations.RoundUpToPowerOf2((uint)minBlockSize)), blockArrayPool); _blockSizeMinus1 = _blockSize - 1; _memoryBlocks = _emptyMemoryBlocksArray; } @@ -399,11 +217,11 @@ namespace Recyclable.Collections if (expectedItemsCount > 0) { minBlockSize = checked((int)BitOperations.RoundUpToPowerOf2((uint)minBlockSize)); - SetupBlockArrayPooling(this, minBlockSize, blockArrayPool); - _capacity = Resize(this, minBlockSize, _blockSizePow2BitShift, expectedItemsCount.Value); + Helpers.SetupBlockArrayPooling(this, minBlockSize, blockArrayPool); + _capacity = Helpers.Resize(this, minBlockSize, _blockSizePow2BitShift, expectedItemsCount.Value); if (minBlockSize != _memoryBlocks![0].Length && _capacity > 0) { - SetupBlockArrayPooling(this, _memoryBlocks[0].Length, blockArrayPool); + Helpers.SetupBlockArrayPooling(this, _memoryBlocks[0].Length, blockArrayPool); _blockSizeMinus1 = _blockSize - 1; } else @@ -413,7 +231,7 @@ namespace Recyclable.Collections } else { - SetupBlockArrayPooling(this, checked((int)BitOperations.RoundUpToPowerOf2((uint)minBlockSize)), blockArrayPool); + Helpers.SetupBlockArrayPooling(this, checked((int)BitOperations.RoundUpToPowerOf2((uint)minBlockSize)), blockArrayPool); _blockSizeMinus1 = _blockSize - 1; _memoryBlocks = _emptyMemoryBlocksArray; } @@ -429,11 +247,11 @@ namespace Recyclable.Collections if (expectedItemsCount > 0) { minBlockSize = checked((int)BitOperations.RoundUpToPowerOf2((uint)minBlockSize)); - SetupBlockArrayPooling(this, minBlockSize, blockArrayPool); - _capacity = Resize(this, minBlockSize, _blockSizePow2BitShift, expectedItemsCount.Value); + Helpers.SetupBlockArrayPooling(this, minBlockSize, blockArrayPool); + _capacity = Helpers.Resize(this, minBlockSize, _blockSizePow2BitShift, expectedItemsCount.Value); if (minBlockSize != _memoryBlocks![0].Length && _capacity > 0) { - SetupBlockArrayPooling(this, _memoryBlocks[0].Length, blockArrayPool); + Helpers.SetupBlockArrayPooling(this, _memoryBlocks[0].Length, blockArrayPool); _blockSizeMinus1 = _blockSize - 1; } else @@ -443,7 +261,7 @@ namespace Recyclable.Collections } else { - SetupBlockArrayPooling(this, checked((int)BitOperations.RoundUpToPowerOf2((uint)minBlockSize)), blockArrayPool); + Helpers.SetupBlockArrayPooling(this, checked((int)BitOperations.RoundUpToPowerOf2((uint)minBlockSize)), blockArrayPool); _blockSizeMinus1 = _blockSize - 1; _memoryBlocks = _emptyMemoryBlocksArray; } @@ -459,11 +277,11 @@ namespace Recyclable.Collections if (expectedItemsCount > 0) { minBlockSize = checked((int)BitOperations.RoundUpToPowerOf2((uint)minBlockSize)); - SetupBlockArrayPooling(this, minBlockSize, blockArrayPool); - _capacity = Resize(this, minBlockSize, _blockSizePow2BitShift, expectedItemsCount.Value); + Helpers.SetupBlockArrayPooling(this, minBlockSize, blockArrayPool); + _capacity = Helpers.Resize(this, minBlockSize, _blockSizePow2BitShift, expectedItemsCount.Value); if (minBlockSize != _memoryBlocks![0].Length && _capacity > 0) { - SetupBlockArrayPooling(this, _memoryBlocks[0].Length, blockArrayPool); + Helpers.SetupBlockArrayPooling(this, _memoryBlocks[0].Length, blockArrayPool); _blockSizeMinus1 = _blockSize - 1; } else @@ -473,7 +291,7 @@ namespace Recyclable.Collections } else { - SetupBlockArrayPooling(this, checked((int)BitOperations.RoundUpToPowerOf2((uint)minBlockSize)), blockArrayPool); + Helpers.SetupBlockArrayPooling(this, checked((int)BitOperations.RoundUpToPowerOf2((uint)minBlockSize)), blockArrayPool); _blockSizeMinus1 = _blockSize - 1; _memoryBlocks = _emptyMemoryBlocksArray; } @@ -489,11 +307,11 @@ namespace Recyclable.Collections if (expectedItemsCount > 0) { minBlockSize = checked((int)BitOperations.RoundUpToPowerOf2((uint)minBlockSize)); - SetupBlockArrayPooling(this, minBlockSize, blockArrayPool); - _capacity = Resize(this, minBlockSize, _blockSizePow2BitShift, expectedItemsCount.Value); + Helpers.SetupBlockArrayPooling(this, minBlockSize, blockArrayPool); + _capacity = Helpers.Resize(this, minBlockSize, _blockSizePow2BitShift, expectedItemsCount.Value); if (minBlockSize != _memoryBlocks![0].Length && _capacity > 0) { - SetupBlockArrayPooling(this, _memoryBlocks[0].Length, blockArrayPool); + Helpers.SetupBlockArrayPooling(this, _memoryBlocks[0].Length, blockArrayPool); _blockSizeMinus1 = _blockSize - 1; } else @@ -503,7 +321,7 @@ namespace Recyclable.Collections } else { - SetupBlockArrayPooling(this, checked((int)BitOperations.RoundUpToPowerOf2((uint)minBlockSize)), blockArrayPool); + Helpers.SetupBlockArrayPooling(this, checked((int)BitOperations.RoundUpToPowerOf2((uint)minBlockSize)), blockArrayPool); _blockSizeMinus1 = _blockSize - 1; _memoryBlocks = _emptyMemoryBlocksArray; } @@ -519,11 +337,11 @@ namespace Recyclable.Collections if (expectedItemsCount > 0) { minBlockSize = checked((int)BitOperations.RoundUpToPowerOf2((uint)minBlockSize)); - SetupBlockArrayPooling(this, minBlockSize, blockArrayPool); - _capacity = Resize(this, minBlockSize, _blockSizePow2BitShift, expectedItemsCount.Value); + Helpers.SetupBlockArrayPooling(this, minBlockSize, blockArrayPool); + _capacity = Helpers.Resize(this, minBlockSize, _blockSizePow2BitShift, expectedItemsCount.Value); if (minBlockSize != _memoryBlocks![0].Length && _capacity > 0) { - SetupBlockArrayPooling(this, _memoryBlocks[0].Length, blockArrayPool); + Helpers.SetupBlockArrayPooling(this, _memoryBlocks[0].Length, blockArrayPool); _blockSizeMinus1 = _blockSize - 1; } else @@ -533,7 +351,7 @@ namespace Recyclable.Collections } else { - SetupBlockArrayPooling(this, checked((int)BitOperations.RoundUpToPowerOf2((uint)minBlockSize)), blockArrayPool); + Helpers.SetupBlockArrayPooling(this, checked((int)BitOperations.RoundUpToPowerOf2((uint)minBlockSize)), blockArrayPool); _blockSizeMinus1 = _blockSize - 1; _memoryBlocks = _emptyMemoryBlocksArray; } @@ -549,11 +367,11 @@ namespace Recyclable.Collections if (expectedItemsCount > 0) { minBlockSize = checked((int)BitOperations.RoundUpToPowerOf2((uint)minBlockSize)); - SetupBlockArrayPooling(this, minBlockSize, blockArrayPool); - _capacity = Resize(this, minBlockSize, _blockSizePow2BitShift, expectedItemsCount.Value); + Helpers.SetupBlockArrayPooling(this, minBlockSize, blockArrayPool); + _capacity = Helpers.Resize(this, minBlockSize, _blockSizePow2BitShift, expectedItemsCount.Value); if (minBlockSize != _memoryBlocks![0].Length && _capacity > 0) { - SetupBlockArrayPooling(this, _memoryBlocks[0].Length, blockArrayPool); + Helpers.SetupBlockArrayPooling(this, _memoryBlocks[0].Length, blockArrayPool); _blockSizeMinus1 = _blockSize - 1; } else @@ -563,7 +381,7 @@ namespace Recyclable.Collections } else { - SetupBlockArrayPooling(this, checked((int)BitOperations.RoundUpToPowerOf2((uint)minBlockSize)), blockArrayPool); + Helpers.SetupBlockArrayPooling(this, checked((int)BitOperations.RoundUpToPowerOf2((uint)minBlockSize)), blockArrayPool); _blockSizeMinus1 = _blockSize - 1; _memoryBlocks = _emptyMemoryBlocksArray; } @@ -579,11 +397,11 @@ namespace Recyclable.Collections if (expectedItemsCount > 0) { minBlockSize = checked((int)BitOperations.RoundUpToPowerOf2((uint)minBlockSize)); - SetupBlockArrayPooling(this, minBlockSize, blockArrayPool); - _capacity = Resize(this, minBlockSize, _blockSizePow2BitShift, expectedItemsCount.Value); + Helpers.SetupBlockArrayPooling(this, minBlockSize, blockArrayPool); + _capacity = Helpers.Resize(this, minBlockSize, _blockSizePow2BitShift, expectedItemsCount.Value); if (minBlockSize != _memoryBlocks![0].Length && _capacity > 0) { - SetupBlockArrayPooling(this, _memoryBlocks[0].Length, blockArrayPool); + Helpers.SetupBlockArrayPooling(this, _memoryBlocks[0].Length, blockArrayPool); _blockSizeMinus1 = _blockSize - 1; } else @@ -593,7 +411,7 @@ namespace Recyclable.Collections } else { - SetupBlockArrayPooling(this, checked((int)BitOperations.RoundUpToPowerOf2((uint)minBlockSize)), blockArrayPool); + Helpers.SetupBlockArrayPooling(this, checked((int)BitOperations.RoundUpToPowerOf2((uint)minBlockSize)), blockArrayPool); _blockSizeMinus1 = _blockSize - 1; _memoryBlocks = _emptyMemoryBlocksArray; } @@ -628,7 +446,7 @@ namespace Recyclable.Collections { if (_capacity < _longCount + 1) { - _ = EnsureCapacity(this, _longCount + 1); + _ = Helpers.EnsureCapacity(this, _longCount + 1); } _memoryBlocks[_nextItemBlockIndex][_nextItemIndex++] = item; @@ -661,7 +479,7 @@ namespace Recyclable.Collections long targetCapacity = _longCount + items.LongLength; if (_capacity < targetCapacity) { - _ = EnsureCapacity(this, targetCapacity); + _ = Helpers.EnsureCapacity(this, targetCapacity); } int blockSize = _blockSize, @@ -710,7 +528,7 @@ namespace Recyclable.Collections long targetCapacity = _longCount + items.Count; if (_capacity < targetCapacity) { - _ = EnsureCapacity(this, targetCapacity); + _ = Helpers.EnsureCapacity(this, targetCapacity); } int blockSize = _blockSize, @@ -751,7 +569,7 @@ namespace Recyclable.Collections long targetCapacity = _longCount + itemsSpan.Length; if (_capacity < targetCapacity) { - _ = EnsureCapacity(this, targetCapacity); + _ = Helpers.EnsureCapacity(this, targetCapacity); } int blockSize = _blockSize, @@ -801,7 +619,7 @@ namespace Recyclable.Collections if (_capacity < targetCapacity) { - _ = EnsureCapacity(this, targetCapacity); + _ = Helpers.EnsureCapacity(this, targetCapacity); } int blockSize = _blockSize, @@ -872,7 +690,7 @@ namespace Recyclable.Collections long targetCapacity = _longCount + items.Count; if (_capacity < targetCapacity) { - _ = EnsureCapacity(this, targetCapacity); + _ = Helpers.EnsureCapacity(this, targetCapacity); } int blockSize = _blockSize, @@ -920,7 +738,7 @@ namespace Recyclable.Collections long targetCapacity = _longCount + items.Count; if (_capacity < targetCapacity) { - _ = EnsureCapacity(this, targetCapacity); + _ = Helpers.EnsureCapacity(this, targetCapacity); } int blockSize = _blockSize, @@ -1145,7 +963,7 @@ namespace Recyclable.Collections if (index < _longCount) { - CopyFollowingItems(this, index); + Helpers.CopyFollowingItems(this, index); } if (_nextItemIndex > 0) @@ -1207,14 +1025,14 @@ namespace Recyclable.Collections { if (index >= _longCount || index < 0) { - ThrowIndexOutOfRangeException($"Argument \"{nameof(index)}\" = {index} is out of range. Expected value between 0 and {_longCount - 1}"); + Helpers.ThrowIndexOutOfRangeException($"Argument \"{nameof(index)}\" = {index} is out of range. Expected value between 0 and {_longCount - 1}"); } _longCount--; if (index < _longCount) { - CopyFollowingItems(this, index); + Helpers.CopyFollowingItems(this, index); } if (_nextItemIndex > 0) @@ -1246,14 +1064,14 @@ namespace Recyclable.Collections { if (index >= _longCount || index < 0) { - ThrowIndexOutOfRangeException($"Argument \"{nameof(index)}\" = {index} is out of range. Expected value between 0 and {_longCount - 1}"); + Helpers.ThrowIndexOutOfRangeException($"Argument \"{nameof(index)}\" = {index} is out of range. Expected value between 0 and {_longCount - 1}"); } _longCount--; if (index < _longCount) { - CopyFollowingItems(this, index); + Helpers.CopyFollowingItems(this, index); } if (_nextItemIndex > 0)