"checked" added/removed, as applicable. Span converted to ReadOnlySpan, where possible. Calls to ReadOnlySpan/Span constructors converted to type-casting, where possible.
This commit is contained in:
1 parent
39d63d1d65
commit
d4d1364628
16 files changed
+204
-137
No files matched your search
@@ -139,9 +139,9 @@
|
||||
1. ✅ `T[]`
|
||||
1. ✅ Release 0.0.5
|
||||
1. ✅ Implement `List<T>` compatibility pack in `RecyclableList<T>`
|
||||
1. 👉 Overflow review
|
||||
1. 🅿️ Add type casting to `long` for `<<` & `>>` operations, where required
|
||||
1. 🅿️ Make type castings `checked`, where required
|
||||
1. ✅ Overflow review
|
||||
1. ✅ Add type casting to `long` for `<<` & `>>` operations, where required
|
||||
1. ✅ Make type castings `checked`, where required
|
||||
1. 🅿️ Release 0.0.6
|
||||
1. 🅿️ Implement `List<T>` compatibility pack in `RecyclableLongList<T>`
|
||||
1. 🅿️ Port `RecyclableLongList<T>` optimizations to `RecyclableList<T>`
|
||||
@@ -191,6 +191,7 @@
|
||||
1. 🅿️ Multi-threading benchmarks
|
||||
1. 🅿️ `SpinLockSlimmer`
|
||||
1. 🅿️ Multi-threading benchmarks
|
||||
1. 🅿️ Remove range operators, where possible
|
||||
1. 🅿️ Release 0.0.14
|
||||
1. 🅿️ Extend unit tests
|
||||
1. 🅿️ `RecyclableLongListExtensions.CopyTo`
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
using BenchmarkDotNet.Attributes;
|
||||
|
||||
namespace Recyclable.Collections.Benchmarks.POC
|
||||
{
|
||||
public enum SpanConstructorVsTypecastingPocBenchmarkType
|
||||
{
|
||||
Unknown,
|
||||
Constructor,
|
||||
TypeCasting,
|
||||
}
|
||||
|
||||
[MemoryDiagnoser]
|
||||
public class SpanConstructorVsTypecastingPocBenchmarks : PocBenchmarkBase<SpanConstructorVsTypecastingPocBenchmarkType>
|
||||
{
|
||||
private int[]? TestData { get; set; }
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)]
|
||||
private void DoNothing(ReadOnlySpan<int> span) { }
|
||||
|
||||
[Params(SpanConstructorVsTypecastingPocBenchmarkType.TypeCasting)]
|
||||
public override SpanConstructorVsTypecastingPocBenchmarkType BaseDataType { get => base.BaseDataType; set => base.BaseDataType = value; }
|
||||
|
||||
[Params(SpanConstructorVsTypecastingPocBenchmarkType.Constructor)]
|
||||
public override SpanConstructorVsTypecastingPocBenchmarkType DataType { get => base.DataType; set => base.DataType = value; }
|
||||
|
||||
[Params(8)]
|
||||
public override int TestObjectCount { get => base.TestObjectCount; set => base.TestObjectCount = value; }
|
||||
|
||||
public static void Run()
|
||||
{
|
||||
var benchmark = new SpanConstructorVsTypecastingPocBenchmarks();
|
||||
benchmark.Setup();
|
||||
benchmark.Constructor();
|
||||
benchmark.TypeCasting();
|
||||
benchmark.Cleanup();
|
||||
}
|
||||
|
||||
public void Constructor()
|
||||
{
|
||||
ReadOnlySpan<int> span = new(TestData);
|
||||
DoNothing(span);
|
||||
}
|
||||
|
||||
public void TypeCasting()
|
||||
{
|
||||
ReadOnlySpan<int> span = TestData;
|
||||
DoNothing(span);
|
||||
}
|
||||
|
||||
public override void Setup()
|
||||
{
|
||||
TestData = new int[TestObjectCount];
|
||||
base.Setup();
|
||||
}
|
||||
|
||||
protected override Action? GetTestMethod(SpanConstructorVsTypecastingPocBenchmarkType benchmarkType) => benchmarkType switch
|
||||
{
|
||||
SpanConstructorVsTypecastingPocBenchmarkType.Constructor => Constructor,
|
||||
SpanConstructorVsTypecastingPocBenchmarkType.TypeCasting => TypeCasting,
|
||||
_ => throw CreateUnknownBenchmarkTypeException(benchmarkType),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -42,7 +42,6 @@ namespace Recyclable.Collections.Benchmarks
|
||||
_ = BenchmarkRunner.Run<BoolOrComparePocBenchmarks>(BenchmarkConfig);
|
||||
_ = BenchmarkRunner.Run<DelegateVsComparerPocBenchmarks>(BenchmarkConfig);
|
||||
_ = BenchmarkRunner.Run<ModuloPocBenchmarks>(BenchmarkConfig);
|
||||
_ = BenchmarkRunner.Run<RecyclableLongListPocBenchmarks>(BenchmarkConfig);
|
||||
_ = BenchmarkRunner.Run<TaskRunVsTaskFactoryStartNewBenchmarks>(BenchmarkConfig);
|
||||
_ = BenchmarkRunner.Run<RefVsInstanceMemberPocBenchmarks>(BenchmarkConfig);
|
||||
_ = BenchmarkRunner.Run<RoundBenchmarks>(BenchmarkConfig);
|
||||
@@ -51,6 +50,7 @@ namespace Recyclable.Collections.Benchmarks
|
||||
_ = BenchmarkRunner.Run<EqualVsContainsInConsecutiveOrderBenchmarks>(BenchmarkConfig);
|
||||
_ = BenchmarkRunner.Run<RoundUpToPowerOf2vsOtherBenchmarks>(BenchmarkConfig);
|
||||
_ = BenchmarkRunner.Run<GreaterOperatorVsDoesntEqualOperatorBenchmarks>(BenchmarkConfig);
|
||||
_ = BenchmarkRunner.Run<SpanConstructorVsTypecastingPocBenchmarks>(BenchmarkConfig);
|
||||
// ArraySizeLimitPocBenchmarks>(BenchmarkConfig);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ using System.Runtime.CompilerServices;
|
||||
namespace Recyclable.Collections
|
||||
{
|
||||
public static class zRecyclableListAddRange
|
||||
{
|
||||
{
|
||||
private static void AddRangeEnumerated<T>(this RecyclableList<T> list, IEnumerable<T> items, int growByCount)
|
||||
{
|
||||
var enumerator = items.GetEnumerator();
|
||||
@@ -19,19 +19,19 @@ namespace Recyclable.Collections
|
||||
available = capacity - targetItemIndex,
|
||||
i;
|
||||
|
||||
Span<T> memorySpan = new(list._memoryBlock);
|
||||
Span<T> targetSpan = list._memoryBlock;
|
||||
do
|
||||
{
|
||||
if (targetItemIndex + growByCount > capacity)
|
||||
{
|
||||
capacity = RecyclableListHelpers<T>.EnsureCapacity(list, targetItemIndex, checked((int)BitOperations.RoundUpToPowerOf2((uint)(targetItemIndex + growByCount))));
|
||||
memorySpan = new(list._memoryBlock);
|
||||
targetSpan = list._memoryBlock;
|
||||
available = capacity - targetItemIndex;
|
||||
}
|
||||
|
||||
for (i = 0; i < available; i++)
|
||||
{
|
||||
memorySpan[targetItemIndex++] = enumerator.Current;
|
||||
targetSpan[targetItemIndex++] = enumerator.Current;
|
||||
if (!enumerator.MoveNext())
|
||||
{
|
||||
break;
|
||||
@@ -48,10 +48,10 @@ namespace Recyclable.Collections
|
||||
{
|
||||
list._capacity = RecyclableListHelpers<T>.EnsureCapacity(list, currentItemsCount, checked((int)BitOperations.RoundUpToPowerOf2((uint)(currentItemsCount + requiredAdditionalCapacity))));
|
||||
|
||||
Span<T> memorySpan = new(list._memoryBlock);
|
||||
Span<T> targetSpan = list._memoryBlock;
|
||||
foreach (var item in items)
|
||||
{
|
||||
memorySpan[currentItemsCount++] = item;
|
||||
targetSpan[currentItemsCount++] = item;
|
||||
}
|
||||
|
||||
list._count = currentItemsCount;
|
||||
@@ -78,7 +78,7 @@ namespace Recyclable.Collections
|
||||
list._capacity = RecyclableListHelpers<T>.EnsureCapacity(list, list._count, checked((int)BitOperations.RoundUpToPowerOf2((uint)(list._count + items.Length))));
|
||||
}
|
||||
|
||||
new Span<T>(items).CopyTo(new Span<T>(list._memoryBlock, list._count, items.Length));
|
||||
new ReadOnlySpan<T>(items).CopyTo(new Span<T>(list._memoryBlock, list._count, items.Length));
|
||||
list._count += items.Length;
|
||||
list._version++;
|
||||
}
|
||||
@@ -156,7 +156,7 @@ namespace Recyclable.Collections
|
||||
list._capacity = RecyclableListHelpers<T>.EnsureCapacity(list, list._count, checked((int)BitOperations.RoundUpToPowerOf2((uint)(list._count + items._count))));
|
||||
}
|
||||
|
||||
new Span<T>(items._memoryBlock, 0, items._count).CopyTo(new Span<T>(list._memoryBlock, list._count, items._count));
|
||||
new ReadOnlySpan<T>(items._memoryBlock, 0, items._count).CopyTo(new Span<T>(list._memoryBlock, list._count, items._count));
|
||||
list._count += items._count;
|
||||
list._version++;
|
||||
}
|
||||
@@ -215,13 +215,13 @@ namespace Recyclable.Collections
|
||||
public static IEnumerator AddRange<T>(this RecyclableList<T> list, IEnumerable source, int growByCount = RecyclableDefaults.MinPooledArrayLength)
|
||||
{
|
||||
int targetItemIndex = list._count;
|
||||
Span<T> memorySpan;
|
||||
Span<T> targetSpan;
|
||||
|
||||
int i;
|
||||
var enumerator = source.GetEnumerator();
|
||||
|
||||
int capacity = list._capacity;
|
||||
memorySpan = new(list._memoryBlock);
|
||||
targetSpan = list._memoryBlock;
|
||||
if (enumerator.MoveNext())
|
||||
{
|
||||
int available = capacity - targetItemIndex;
|
||||
@@ -230,13 +230,13 @@ namespace Recyclable.Collections
|
||||
if (targetItemIndex + growByCount > capacity)
|
||||
{
|
||||
capacity = RecyclableListHelpers<T>.EnsureCapacity(list, targetItemIndex, checked((int)BitOperations.RoundUpToPowerOf2((uint)(targetItemIndex + growByCount))));
|
||||
memorySpan = new(list._memoryBlock);
|
||||
targetSpan = list._memoryBlock;
|
||||
available = capacity - targetItemIndex;
|
||||
}
|
||||
|
||||
for (i = 0; i < available; i++)
|
||||
{
|
||||
memorySpan[targetItemIndex++] = (T)enumerator.Current;
|
||||
targetSpan[targetItemIndex++] = (T)enumerator.Current;
|
||||
if (!enumerator.MoveNext())
|
||||
{
|
||||
break;
|
||||
@@ -259,10 +259,10 @@ namespace Recyclable.Collections
|
||||
list._capacity = RecyclableListHelpers<T>.EnsureCapacity(list, list._count, checked((int)BitOperations.RoundUpToPowerOf2((uint)(list._count + sourceItemsCount))));
|
||||
}
|
||||
|
||||
Span<T> memorySpan = new(list._memoryBlock, list._count, sourceItemsCount);
|
||||
Span<T> targetSpan = new(list._memoryBlock, list._count, sourceItemsCount);
|
||||
for (var sourceItemIndex = 0; sourceItemIndex < sourceItemsCount; sourceItemIndex++)
|
||||
{
|
||||
memorySpan[sourceItemIndex] = items[sourceItemIndex];
|
||||
targetSpan[sourceItemIndex] = items[sourceItemIndex];
|
||||
}
|
||||
|
||||
list._count += sourceItemsCount;
|
||||
@@ -314,5 +314,5 @@ namespace Recyclable.Collections
|
||||
list._version++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,7 @@ namespace Recyclable.Collections
|
||||
return false;
|
||||
}
|
||||
|
||||
ReadOnlySpan<T> sourceSpan = new(list._memoryBlock);
|
||||
ReadOnlySpan<T> sourceSpan = list._memoryBlock;
|
||||
for (var itemIndex = 0; itemIndex < sourceItemsCount; itemIndex++)
|
||||
{
|
||||
if (match(sourceSpan[itemIndex]))
|
||||
@@ -32,7 +32,7 @@ namespace Recyclable.Collections
|
||||
return default;
|
||||
}
|
||||
|
||||
ReadOnlySpan<T> sourceSpan = new(list._memoryBlock);
|
||||
ReadOnlySpan<T> sourceSpan = list._memoryBlock;
|
||||
for (var itemIndex = 0; itemIndex < sourceItemsCount; itemIndex++)
|
||||
{
|
||||
if (match(sourceSpan[itemIndex]))
|
||||
@@ -52,7 +52,7 @@ namespace Recyclable.Collections
|
||||
return new();
|
||||
}
|
||||
|
||||
ReadOnlySpan<T> sourceSpan = new(list._memoryBlock);
|
||||
ReadOnlySpan<T> sourceSpan = list._memoryBlock;
|
||||
RecyclableList<T> result = new(sourceItemsCount >> 3);
|
||||
Span<T> resultSpan = result._memoryBlock;
|
||||
int capacity = result._capacity,
|
||||
@@ -85,7 +85,7 @@ namespace Recyclable.Collections
|
||||
return new();
|
||||
}
|
||||
|
||||
ReadOnlySpan<T> sourceSpan = new(list._memoryBlock);
|
||||
ReadOnlySpan<T> sourceSpan = list._memoryBlock;
|
||||
RecyclableList<int> result = new(sourceItemsCount >> 3);
|
||||
Span<int> resultSpan = result._memoryBlock;
|
||||
int capacity = result._capacity,
|
||||
@@ -120,7 +120,7 @@ namespace Recyclable.Collections
|
||||
}
|
||||
|
||||
sourceItemsCount = Math.Min(sourceItemsCount, startIndex + sourceItemsCount);
|
||||
ReadOnlySpan<T> sourceSpan = new(list._memoryBlock);
|
||||
ReadOnlySpan<T> sourceSpan = list._memoryBlock;
|
||||
for (var itemIndex = startIndex; itemIndex < sourceItemsCount; itemIndex++)
|
||||
{
|
||||
if (match(sourceSpan[itemIndex]))
|
||||
@@ -141,7 +141,7 @@ namespace Recyclable.Collections
|
||||
}
|
||||
|
||||
sourceItemsCount = Math.Min(sourceItemsCount, startIndex + sourceItemsCount);
|
||||
ReadOnlySpan<T> sourceSpan = new(list._memoryBlock);
|
||||
ReadOnlySpan<T> sourceSpan = list._memoryBlock;
|
||||
for (var itemIndex = startIndex; itemIndex < sourceItemsCount; itemIndex++)
|
||||
{
|
||||
if (match(sourceSpan[itemIndex]))
|
||||
@@ -161,7 +161,7 @@ namespace Recyclable.Collections
|
||||
return RecyclableDefaults.ItemNotFoundIndex;
|
||||
}
|
||||
|
||||
ReadOnlySpan<T> sourceSpan = new(list._memoryBlock);
|
||||
ReadOnlySpan<T> sourceSpan = list._memoryBlock;
|
||||
for (var itemIndex = 0; itemIndex < sourceItemsCount; itemIndex++)
|
||||
{
|
||||
if (match(sourceSpan[itemIndex]))
|
||||
@@ -180,7 +180,7 @@ namespace Recyclable.Collections
|
||||
return default;
|
||||
}
|
||||
|
||||
ReadOnlySpan<T> sourceSpan = new(list._memoryBlock);
|
||||
ReadOnlySpan<T> sourceSpan = list._memoryBlock;
|
||||
for (var itemIndex = list._count - 1; itemIndex >= 0; itemIndex--)
|
||||
{
|
||||
if (match(sourceSpan[itemIndex]))
|
||||
@@ -218,7 +218,7 @@ namespace Recyclable.Collections
|
||||
}
|
||||
|
||||
int lastItemIndex = startIndex - sourceItemsCount;
|
||||
ReadOnlySpan<T> sourceSpan = new(list._memoryBlock);
|
||||
ReadOnlySpan<T> sourceSpan = list._memoryBlock;
|
||||
for (var itemIndex = startIndex; itemIndex > lastItemIndex; itemIndex--)
|
||||
{
|
||||
if (match(sourceSpan[itemIndex]))
|
||||
@@ -237,7 +237,7 @@ namespace Recyclable.Collections
|
||||
return RecyclableDefaults.ItemNotFoundIndex;
|
||||
}
|
||||
|
||||
ReadOnlySpan<T> sourceSpan = new(list._memoryBlock);
|
||||
ReadOnlySpan<T> sourceSpan = list._memoryBlock;
|
||||
for (var itemIndex = startIndex; itemIndex >= 0; itemIndex--)
|
||||
{
|
||||
if (match(sourceSpan[itemIndex]))
|
||||
@@ -256,7 +256,7 @@ namespace Recyclable.Collections
|
||||
return RecyclableDefaults.ItemNotFoundIndex;
|
||||
}
|
||||
|
||||
ReadOnlySpan<T> sourceSpan = new(list._memoryBlock);
|
||||
ReadOnlySpan<T> sourceSpan = list._memoryBlock;
|
||||
for (var itemIndex = list._count - 1; itemIndex >= 0; itemIndex--)
|
||||
{
|
||||
if (match(sourceSpan[itemIndex]))
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace Recyclable.Collections
|
||||
Array.Copy(memoryBlock, index, memoryBlock, capacity - movingBlockLength, movingBlockLength);
|
||||
}
|
||||
|
||||
Span<T> memorySpan = new(memoryBlock);
|
||||
Span<T> memorySpan = memoryBlock;
|
||||
do
|
||||
{
|
||||
if (index + available + movingBlockLength > capacity)
|
||||
@@ -34,7 +34,7 @@ namespace Recyclable.Collections
|
||||
var capacityBeforeIncrease = capacity;
|
||||
capacity = checked((int)BitOperations.RoundUpToPowerOf2((uint)(capacity + growByCount)));
|
||||
_ = RecyclableListHelpers<T>.EnsureCapacity(list, memoryBlock.Length, capacity);
|
||||
memorySpan = new(memoryBlock = list._memoryBlock);
|
||||
memorySpan = memoryBlock = list._memoryBlock;
|
||||
available = capacity - index - movingBlockLength;
|
||||
Array.Copy(memoryBlock, capacityBeforeIncrease - movingBlockLength, memoryBlock, capacity - movingBlockLength, movingBlockLength);
|
||||
}
|
||||
@@ -71,7 +71,7 @@ namespace Recyclable.Collections
|
||||
list._capacity = RecyclableListHelpers<T>.EnsureCapacity(list, currentItemsCount, checked((int)BitOperations.RoundUpToPowerOf2((uint)(currentItemsCount + requiredAdditionalCapacity))));
|
||||
|
||||
Array.Copy(list._memoryBlock, index, list._memoryBlock, index + requiredAdditionalCapacity, list._count - index);
|
||||
Span<T> memorySpan = new(list._memoryBlock);
|
||||
Span<T> memorySpan = list._memoryBlock;
|
||||
foreach (var item in items)
|
||||
{
|
||||
memorySpan[index++] = item;
|
||||
@@ -106,7 +106,7 @@ namespace Recyclable.Collections
|
||||
|
||||
T[] memoryBlock = list._memoryBlock;
|
||||
Array.Copy(memoryBlock, index, memoryBlock, index + items.Length, list._count - index);
|
||||
new Span<T>(items).CopyTo(new Span<T>(memoryBlock, index, items.Length));
|
||||
new ReadOnlySpan<T>(items).CopyTo(new Span<T>(memoryBlock, index, items.Length));
|
||||
list._count += items.Length;
|
||||
list._version++;
|
||||
}
|
||||
@@ -196,7 +196,7 @@ namespace Recyclable.Collections
|
||||
|
||||
T[] memoryBlock = list._memoryBlock;
|
||||
Array.Copy(memoryBlock, index, memoryBlock, index + items.Count, list._count - index);
|
||||
new Span<T>(items._memoryBlock, 0, items._count).CopyTo(new(list._memoryBlock, index, items._count));
|
||||
new ReadOnlySpan<T>(items._memoryBlock, 0, items._count).CopyTo(new(list._memoryBlock, index, items._count));
|
||||
list._count += items._count;
|
||||
list._version++;
|
||||
}
|
||||
@@ -262,7 +262,7 @@ namespace Recyclable.Collections
|
||||
var enumerator = source.GetEnumerator();
|
||||
|
||||
int capacity = list._capacity;
|
||||
memorySpan = new(list._memoryBlock);
|
||||
memorySpan = list._memoryBlock;
|
||||
if (enumerator.MoveNext())
|
||||
{
|
||||
int available = capacity - targetItemIndex;
|
||||
@@ -271,7 +271,7 @@ namespace Recyclable.Collections
|
||||
if (targetItemIndex + growByCount > capacity)
|
||||
{
|
||||
capacity = RecyclableListHelpers<T>.EnsureCapacity(list, targetItemIndex, checked((int)BitOperations.RoundUpToPowerOf2((uint)(targetItemIndex + growByCount))));
|
||||
memorySpan = new(list._memoryBlock);
|
||||
memorySpan = list._memoryBlock;
|
||||
available = capacity - targetItemIndex;
|
||||
}
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace Recyclable.Collections
|
||||
return;
|
||||
}
|
||||
|
||||
ReadOnlySpan<T> sourceSpan = new(list._memoryBlock);
|
||||
ReadOnlySpan<T> sourceSpan = list._memoryBlock;
|
||||
for (var itemIndex = 0; itemIndex < sourceItemsCount; itemIndex++)
|
||||
{
|
||||
action(sourceSpan[itemIndex]);
|
||||
@@ -65,14 +65,14 @@ namespace Recyclable.Collections
|
||||
return new();
|
||||
}
|
||||
|
||||
ReadOnlySpan<T> sourceSpan = new(list._memoryBlock);
|
||||
ReadOnlySpan<T> sourceSpan = list._memoryBlock;
|
||||
RecyclableList<T> result = new(sourceItemsCount);
|
||||
Span<T> resultSpan = result._memoryBlock;
|
||||
Span<T> targetSpan = result._memoryBlock;
|
||||
int resultItemsCount = 0;
|
||||
sourceItemsCount += index;
|
||||
for (var itemIndex = index; itemIndex < sourceItemsCount; itemIndex++)
|
||||
{
|
||||
resultSpan[resultItemsCount++] = sourceSpan[itemIndex];
|
||||
targetSpan[resultItemsCount++] = sourceSpan[itemIndex];
|
||||
}
|
||||
|
||||
result._count = resultItemsCount;
|
||||
@@ -166,7 +166,7 @@ namespace Recyclable.Collections
|
||||
public static T[] ToArray<T>(this RecyclableList<T> list)
|
||||
{
|
||||
T[] result = new T[list._count];
|
||||
new Span<T>(list._memoryBlock, 0, list._count).CopyTo(new Span<T>(result));
|
||||
new ReadOnlySpan<T>(list._memoryBlock, 0, list._count).CopyTo(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -179,7 +179,7 @@ namespace Recyclable.Collections
|
||||
? RecyclableArrayPool<T>.RentShared(requiredCapacity)
|
||||
: new T[requiredCapacity];
|
||||
|
||||
new Span<T>(oldMemoryBlock, 0, list._count).CopyTo(new(result));
|
||||
new ReadOnlySpan<T>(oldMemoryBlock, 0, list._count).CopyTo(result);
|
||||
|
||||
if (oldMemoryBlock.Length >= RecyclableDefaults.MinPooledArrayLength)
|
||||
{
|
||||
@@ -198,7 +198,7 @@ namespace Recyclable.Collections
|
||||
return false;
|
||||
}
|
||||
|
||||
ReadOnlySpan<T> sourceSpan = new(list._memoryBlock);
|
||||
ReadOnlySpan<T> sourceSpan = list._memoryBlock;
|
||||
for (var itemIndex = 0; itemIndex < sourceItemsCount; itemIndex++)
|
||||
{
|
||||
if (!match(sourceSpan[itemIndex]))
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace Recyclable.Collections
|
||||
: RecyclableArrayPool<T>.RentShared(list._capacity);
|
||||
|
||||
// & WAS SLOWER WITHOUT
|
||||
new Span<T>(oldMemoryBlock, 0, list._count).CopyTo(list._memoryBlock);
|
||||
new ReadOnlySpan<T>(oldMemoryBlock, 0, list._count).CopyTo(list._memoryBlock);
|
||||
|
||||
if (oldMemoryBlock.Length >= RecyclableDefaults.MinPooledArrayLength)
|
||||
{
|
||||
@@ -43,7 +43,7 @@ namespace Recyclable.Collections
|
||||
: new T[newSize];
|
||||
|
||||
// & WAS SLOWER AS ARRAY
|
||||
new Span<T>(oldMemoryBlock, 0, sourceList._capacity).CopyTo(sourceList._memoryBlock);
|
||||
new ReadOnlySpan<T>(oldMemoryBlock, 0, sourceList._capacity).CopyTo(sourceList._memoryBlock);
|
||||
|
||||
if (oldMemoryBlock.Length >= RecyclableDefaults.MinPooledArrayLength)
|
||||
{
|
||||
@@ -69,7 +69,7 @@ namespace Recyclable.Collections
|
||||
: new T[newSize];
|
||||
|
||||
// & WAS SLOWER AS ARRAY
|
||||
new Span<T>(oldMemoryBlock, 0, oldSize).CopyTo(sourceList._memoryBlock);
|
||||
new ReadOnlySpan<T>(oldMemoryBlock, 0, oldSize).CopyTo(sourceList._memoryBlock);
|
||||
|
||||
if (oldMemoryBlock.Length >= RecyclableDefaults.MinPooledArrayLength)
|
||||
{
|
||||
|
||||
@@ -222,7 +222,7 @@ namespace Recyclable.Collections
|
||||
}
|
||||
else
|
||||
{
|
||||
_capacity = RecyclableListHelpers<T>.EnsureCapacity(this, (int)BitOperations.RoundUpToPowerOf2((uint)_capacity));
|
||||
_capacity = RecyclableListHelpers<T>.EnsureCapacity(this, checked((int)BitOperations.RoundUpToPowerOf2((uint)_capacity)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -273,7 +273,7 @@ namespace Recyclable.Collections
|
||||
{
|
||||
// TODO: Compare performance
|
||||
// Array.Copy(_memoryBlock, index, _memoryBlock, index + 1, oldCount);
|
||||
new Span<T>(_memoryBlock, index, oldCount -= index)
|
||||
new ReadOnlySpan<T>(_memoryBlock, index, oldCount -= index)
|
||||
.CopyTo(new Span<T>(_memoryBlock, index + 1, oldCount));
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace Recyclable.Collections
|
||||
available = capacity - copied,
|
||||
i;
|
||||
|
||||
Span<T[]> memoryBlocksSpan = new(targetList._memoryBlocks);
|
||||
ReadOnlySpan<T[]> memoryBlocksSpan = targetList._memoryBlocks;
|
||||
Span<T> blockArraySpan;
|
||||
|
||||
while (true)
|
||||
@@ -31,11 +31,11 @@ namespace Recyclable.Collections
|
||||
if (copied + blockSize > capacity)
|
||||
{
|
||||
capacity = RecyclableLongList<T>.Helpers.Resize(targetList, blockSize, targetList._blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)(capacity + blockSize))));
|
||||
memoryBlocksSpan = new(targetList._memoryBlocks);
|
||||
memoryBlocksSpan = targetList._memoryBlocks;
|
||||
available = capacity - copied;
|
||||
}
|
||||
|
||||
blockArraySpan = new(memoryBlocksSpan[targetBlockIdx]);
|
||||
blockArraySpan = memoryBlocksSpan[targetBlockIdx];
|
||||
for (i = 1; i <= available; i++)
|
||||
{
|
||||
blockArraySpan[targetItemIdx++] = enumerator.Current;
|
||||
@@ -69,7 +69,7 @@ namespace Recyclable.Collections
|
||||
break;
|
||||
}
|
||||
|
||||
blockArraySpan = new(memoryBlocksSpan[targetBlockIdx]);
|
||||
blockArraySpan = memoryBlocksSpan[targetBlockIdx];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,8 +94,8 @@ namespace Recyclable.Collections
|
||||
targetList._capacity = RecyclableLongList<T>.Helpers.Resize(targetList, blockSize, targetList._blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)requiredCapacity)));
|
||||
}
|
||||
|
||||
Span<T[]> memoryBlocksSpan = new(targetList._memoryBlocks);
|
||||
Span<T> blockArraySpan = new(memoryBlocksSpan[targetBlockIdx]);
|
||||
ReadOnlySpan<T[]> memoryBlocksSpan = targetList._memoryBlocks;
|
||||
Span<T> blockArraySpan = memoryBlocksSpan[targetBlockIdx];
|
||||
foreach (var item in items)
|
||||
{
|
||||
blockArraySpan[targetItemIdx++] = item;
|
||||
@@ -108,7 +108,7 @@ namespace Recyclable.Collections
|
||||
break;
|
||||
}
|
||||
|
||||
blockArraySpan = new Span<T>(memoryBlocksSpan[targetBlockIdx]);
|
||||
blockArraySpan = memoryBlocksSpan[targetBlockIdx];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,7 +138,7 @@ namespace Recyclable.Collections
|
||||
targetList._capacity = RecyclableLongList<T>.Helpers.Resize(targetList, blockSize, targetList._blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)targetCapacity)));
|
||||
}
|
||||
|
||||
Span<T[]> memoryBlocksSpan = new(targetList._memoryBlocks);
|
||||
ReadOnlySpan<T[]> memoryBlocksSpan = targetList._memoryBlocks;
|
||||
Array.Copy(items, 0, memoryBlocksSpan[targetBlockIndex++], targetList._nextItemIndex, sourceItemIndex);
|
||||
while (sourceItemIndex < fullBlockItemsCount)
|
||||
{
|
||||
@@ -165,7 +165,7 @@ namespace Recyclable.Collections
|
||||
}
|
||||
else
|
||||
{
|
||||
targetList._nextItemIndex += (int)sourceItemIndex;
|
||||
targetList._nextItemIndex += checked((int)sourceItemIndex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,11 +189,11 @@ namespace Recyclable.Collections
|
||||
|
||||
// We're better off to temporarily copy it to a fixed array,
|
||||
// than copying them item by item. We may run into OOMs, though.
|
||||
T[] itemsBuffer = items.Count >= RecyclableDefaults.MinPooledArrayLength ? RecyclableArrayPool<T>.RentShared((int)BitOperations.RoundUpToPowerOf2((uint)items.Count)) : new T[items.Count];
|
||||
T[] itemsBuffer = items.Count >= RecyclableDefaults.MinPooledArrayLength ? RecyclableArrayPool<T>.RentShared(checked((int)BitOperations.RoundUpToPowerOf2((uint)items.Count))) : new T[items.Count];
|
||||
items.CopyTo(itemsBuffer, 0);
|
||||
|
||||
Span<T> itemsSpan = new(itemsBuffer, 0, items.Count);
|
||||
Span<T[]> memoryBlocksSpan = new(targetList._memoryBlocks);
|
||||
ReadOnlySpan<T> itemsSpan = new(itemsBuffer, 0, items.Count);
|
||||
ReadOnlySpan<T[]> memoryBlocksSpan = targetList._memoryBlocks;
|
||||
Span<T> targetBlockArraySpan = new(memoryBlocksSpan[targetBlockIndex], targetList._nextItemIndex, targetList._blockSize - targetList._nextItemIndex);
|
||||
while (targetBlockArraySpan.Length <= itemsSpan.Length)
|
||||
{
|
||||
@@ -205,7 +205,7 @@ namespace Recyclable.Collections
|
||||
break;
|
||||
}
|
||||
|
||||
targetBlockArraySpan = new(memoryBlocksSpan[targetBlockIndex]);
|
||||
targetBlockArraySpan = memoryBlocksSpan[targetBlockIndex];
|
||||
}
|
||||
|
||||
if (itemsSpan.Length > 0)
|
||||
@@ -255,12 +255,12 @@ namespace Recyclable.Collections
|
||||
|
||||
// We're better off to temporarily copy it to a fixed array,
|
||||
// than copying them item by item. We may run into OOMs, though.
|
||||
T[] itemsBuffer = items.Count >= RecyclableDefaults.MinPooledArrayLength ? RecyclableArrayPool<T>.RentShared((int)BitOperations.RoundUpToPowerOf2((uint)items.Count)) : new T[items.Count];
|
||||
T[] itemsBuffer = items.Count >= RecyclableDefaults.MinPooledArrayLength ? RecyclableArrayPool<T>.RentShared(checked((int)BitOperations.RoundUpToPowerOf2((uint)items.Count))) : new T[items.Count];
|
||||
|
||||
items.CopyTo(itemsBuffer, 0);
|
||||
|
||||
Span<T> itemsSpan = new(itemsBuffer, 0, items.Count);
|
||||
Span<T[]> memoryBlocksSpan = new(targetList._memoryBlocks);
|
||||
ReadOnlySpan<T> itemsSpan = new(itemsBuffer, 0, items.Count);
|
||||
ReadOnlySpan<T[]> memoryBlocksSpan = targetList._memoryBlocks;
|
||||
Span<T> targetBlockArraySpan = new(memoryBlocksSpan[targetBlockIndex], targetList._nextItemIndex, targetList._blockSize - targetList._nextItemIndex);
|
||||
|
||||
while (targetBlockArraySpan.Length <= itemsSpan.Length)
|
||||
@@ -273,7 +273,7 @@ namespace Recyclable.Collections
|
||||
break;
|
||||
}
|
||||
|
||||
targetBlockArraySpan = new(memoryBlocksSpan[targetBlockIndex]);
|
||||
targetBlockArraySpan = memoryBlocksSpan[targetBlockIndex];
|
||||
}
|
||||
|
||||
if (itemsSpan.Length > 0)
|
||||
@@ -323,7 +323,7 @@ namespace Recyclable.Collections
|
||||
available = capacity - copied,
|
||||
i;
|
||||
|
||||
Span<T[]> memoryBlocksSpan = new(targetList._memoryBlocks);
|
||||
ReadOnlySpan<T[]> memoryBlocksSpan = targetList._memoryBlocks;
|
||||
Span<T> blockArraySpan;
|
||||
|
||||
while (true)
|
||||
@@ -331,11 +331,11 @@ namespace Recyclable.Collections
|
||||
if (copied + blockSize > capacity)
|
||||
{
|
||||
capacity = RecyclableLongList<T>.Helpers.Resize(targetList, blockSize, targetList._blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)(capacity + blockSize))));
|
||||
memoryBlocksSpan = new(targetList._memoryBlocks);
|
||||
memoryBlocksSpan = targetList._memoryBlocks;
|
||||
available = capacity - copied;
|
||||
}
|
||||
|
||||
blockArraySpan = new(memoryBlocksSpan[targetBlockIdx]);
|
||||
blockArraySpan = memoryBlocksSpan[targetBlockIdx];
|
||||
for (i = 1; i <= available; i++)
|
||||
{
|
||||
blockArraySpan[targetItemIdx++] = (T)enumerator.Current;
|
||||
@@ -369,7 +369,7 @@ namespace Recyclable.Collections
|
||||
break;
|
||||
}
|
||||
|
||||
blockArraySpan = new(memoryBlocksSpan[targetBlockIdx]);
|
||||
blockArraySpan = memoryBlocksSpan[targetBlockIdx];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -446,8 +446,8 @@ namespace Recyclable.Collections
|
||||
targetList._capacity = RecyclableLongList<T>.Helpers.Resize(targetList, blockSize, targetList._blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)requiredCapacity)));
|
||||
}
|
||||
|
||||
Span<T[]> memoryBlocksSpan = new(targetList._memoryBlocks);
|
||||
Span<T> blockArraySpan = new(memoryBlocksSpan[targetBlockIdx]);
|
||||
ReadOnlySpan<T[]> memoryBlocksSpan = targetList._memoryBlocks;
|
||||
Span<T> blockArraySpan = memoryBlocksSpan[targetBlockIdx];
|
||||
|
||||
for (var itemIndex = 0; itemIndex < sourceItemsCount; itemIndex++)
|
||||
{
|
||||
@@ -461,7 +461,7 @@ namespace Recyclable.Collections
|
||||
break;
|
||||
}
|
||||
|
||||
blockArraySpan = new Span<T>(memoryBlocksSpan[targetBlockIdx]);
|
||||
blockArraySpan = memoryBlocksSpan[targetBlockIdx];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -489,7 +489,7 @@ namespace Recyclable.Collections
|
||||
targetList._capacity = RecyclableLongList<T>.Helpers.Resize(targetList, blockSize, targetList._blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)targetCapacity)));
|
||||
}
|
||||
|
||||
Span<T[]> memoryBlocksSpan = new(targetList._memoryBlocks);
|
||||
ReadOnlySpan<T[]> memoryBlocksSpan = targetList._memoryBlocks;
|
||||
items.CopyTo(0, memoryBlocksSpan[targetBlockIndex], targetList._nextItemIndex, copied);
|
||||
|
||||
if (targetList._nextItemIndex + copied == blockSize)
|
||||
@@ -535,7 +535,7 @@ namespace Recyclable.Collections
|
||||
targetList._capacity = RecyclableLongList<T>.Helpers.Resize(targetList, targetList._blockSize, targetList._blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)targetCapacity)));
|
||||
}
|
||||
|
||||
Span<T[]> memoryBlocksSpan = new(targetList._memoryBlocks);
|
||||
ReadOnlySpan<T[]> memoryBlocksSpan = targetList._memoryBlocks;
|
||||
Span<T> targetBlockArraySpan = new(memoryBlocksSpan[targetBlockIndex], targetList._nextItemIndex, targetList._blockSize - targetList._nextItemIndex);
|
||||
|
||||
while (items.Length >= targetBlockArraySpan.Length)
|
||||
@@ -548,7 +548,7 @@ namespace Recyclable.Collections
|
||||
}
|
||||
|
||||
targetBlockIndex++;
|
||||
targetBlockArraySpan = new(memoryBlocksSpan[targetBlockIndex]);
|
||||
targetBlockArraySpan = memoryBlocksSpan[targetBlockIndex];
|
||||
}
|
||||
|
||||
if (items.Length > 0)
|
||||
@@ -590,8 +590,8 @@ namespace Recyclable.Collections
|
||||
targetList._capacity = RecyclableLongList<T>.Helpers.Resize(targetList, targetList._blockSize, targetList._blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)targetCapacity)));
|
||||
}
|
||||
|
||||
Span<T> itemsSpan = new(items._memoryBlock, 0, items._count);
|
||||
Span<T[]> targetMemoryBlocksSpan = new(targetList._memoryBlocks);
|
||||
ReadOnlySpan<T> itemsSpan = new(items._memoryBlock, 0, items._count);
|
||||
ReadOnlySpan<T[]> targetMemoryBlocksSpan = targetList._memoryBlocks;
|
||||
Span<T> targetBlockArraySpan = new(targetMemoryBlocksSpan[targetBlockIndex], targetList._nextItemIndex, targetList._blockSize - targetList._nextItemIndex);
|
||||
|
||||
while (itemsSpan.Length >= targetBlockArraySpan.Length)
|
||||
@@ -604,7 +604,7 @@ namespace Recyclable.Collections
|
||||
break;
|
||||
}
|
||||
|
||||
targetBlockArraySpan = new(targetMemoryBlocksSpan[targetBlockIndex]);
|
||||
targetBlockArraySpan = targetMemoryBlocksSpan[targetBlockIndex];
|
||||
}
|
||||
|
||||
if (itemsSpan.Length > 0)
|
||||
@@ -652,20 +652,20 @@ namespace Recyclable.Collections
|
||||
targetList._capacity = RecyclableLongList<T>.Helpers.Resize(targetList, targetList._blockSize, targetList._blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)targetCapacity)));
|
||||
}
|
||||
|
||||
Span<T[]> sourceMemoryBlocksSpan = new(items._memoryBlocks);
|
||||
Span<T> itemsSpan = new(sourceMemoryBlocksSpan[sourceBlockIndex]);
|
||||
Span<T[]> targetMemoryBlocksSpan = new(targetList._memoryBlocks);
|
||||
ReadOnlySpan<T[]> sourceMemoryBlocksSpan = items._memoryBlocks;
|
||||
ReadOnlySpan<T> itemsSpan = sourceMemoryBlocksSpan[sourceBlockIndex];
|
||||
ReadOnlySpan<T[]> targetMemoryBlocksSpan = targetList._memoryBlocks;
|
||||
Span<T> targetBlockArraySpan = new(targetMemoryBlocksSpan[targetBlockIndex], targetList._nextItemIndex, targetList._blockSize - targetList._nextItemIndex);
|
||||
|
||||
while (copiedCount < itemsCount)
|
||||
{
|
||||
toCopy = checked((int)Math.Min(itemsCount - copiedCount, itemsSpan.Length));
|
||||
toCopy = (int)Math.Min(itemsCount - copiedCount, itemsSpan.Length);
|
||||
if (targetBlockArraySpan.Length < toCopy)
|
||||
{
|
||||
toCopy = targetBlockArraySpan.Length;
|
||||
itemsSpan[..toCopy].CopyTo(targetBlockArraySpan);
|
||||
targetBlockIndex++;
|
||||
targetBlockArraySpan = new(targetMemoryBlocksSpan[targetBlockIndex]);
|
||||
targetBlockArraySpan = targetMemoryBlocksSpan[targetBlockIndex];
|
||||
itemsSpan = itemsSpan[toCopy..];
|
||||
copiedCount += toCopy;
|
||||
}
|
||||
@@ -677,14 +677,14 @@ namespace Recyclable.Collections
|
||||
if (itemsSpan.IsEmpty && sourceBlockIndex + 1 < sourceMemoryBlocksSpan.Length)
|
||||
{
|
||||
sourceBlockIndex++;
|
||||
itemsSpan = new(sourceMemoryBlocksSpan[sourceBlockIndex]);
|
||||
itemsSpan = sourceMemoryBlocksSpan[sourceBlockIndex];
|
||||
}
|
||||
|
||||
copiedCount += toCopy;
|
||||
if (targetBlockArraySpan.IsEmpty && copiedCount < itemsCount)
|
||||
{
|
||||
targetBlockIndex++;
|
||||
targetBlockArraySpan = new(targetMemoryBlocksSpan[targetBlockIndex]);
|
||||
targetBlockArraySpan = targetMemoryBlocksSpan[targetBlockIndex];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -697,7 +697,7 @@ namespace Recyclable.Collections
|
||||
}
|
||||
else
|
||||
{
|
||||
targetList._nextItemIndex = checked((int)(targetCapacity & targetList._blockSizeMinus1));
|
||||
targetList._nextItemIndex = (int)(targetCapacity & targetList._blockSizeMinus1);
|
||||
targetList._nextItemBlockIndex = targetBlockIndex;
|
||||
}
|
||||
|
||||
@@ -712,15 +712,15 @@ namespace Recyclable.Collections
|
||||
return;
|
||||
}
|
||||
|
||||
int targetBlockIndex = targetList._nextItemBlockIndex;
|
||||
|
||||
int targetBlockIndex = targetList._nextItemBlockIndex;
|
||||
long targetCapacity = targetList._longCount + items.Length;
|
||||
|
||||
if (targetList._capacity < targetCapacity)
|
||||
{
|
||||
targetList._capacity = RecyclableLongList<T>.Helpers.Resize(targetList, targetList._blockSize, targetList._blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)targetCapacity)));
|
||||
}
|
||||
|
||||
Span<T[]> memoryBlocksSpan = new(targetList._memoryBlocks);
|
||||
ReadOnlySpan<T[]> memoryBlocksSpan = targetList._memoryBlocks;
|
||||
Span<T> targetBlockArraySpan = new(memoryBlocksSpan[targetBlockIndex], targetList._nextItemIndex, targetList._blockSize - targetList._nextItemIndex);
|
||||
|
||||
while (items.Length >= targetBlockArraySpan.Length)
|
||||
@@ -733,7 +733,7 @@ namespace Recyclable.Collections
|
||||
}
|
||||
|
||||
targetBlockIndex++;
|
||||
targetBlockArraySpan = new(memoryBlocksSpan[targetBlockIndex]);
|
||||
targetBlockArraySpan = memoryBlocksSpan[targetBlockIndex];
|
||||
}
|
||||
|
||||
if (items.Length > 0)
|
||||
@@ -775,8 +775,8 @@ namespace Recyclable.Collections
|
||||
targetList._capacity = RecyclableLongList<T>.Helpers.Resize(targetList, targetList._blockSize, targetList._blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)targetCapacity)));
|
||||
}
|
||||
|
||||
Span<T> itemsSpan = new(items);
|
||||
Span<T[]> memoryBlocksSpan = new(targetList._memoryBlocks);
|
||||
ReadOnlySpan<T> itemsSpan = items;
|
||||
ReadOnlySpan<T[]> memoryBlocksSpan = targetList._memoryBlocks;
|
||||
Span<T> targetBlockArraySpan = new(memoryBlocksSpan[targetBlockIndex], targetList._nextItemIndex, targetList._blockSize - targetList._nextItemIndex);
|
||||
|
||||
while (itemsSpan.Length >= targetBlockArraySpan.Length)
|
||||
@@ -789,7 +789,7 @@ namespace Recyclable.Collections
|
||||
}
|
||||
|
||||
targetBlockIndex++;
|
||||
targetBlockArraySpan = new(memoryBlocksSpan[targetBlockIndex]);
|
||||
targetBlockArraySpan = memoryBlocksSpan[targetBlockIndex];
|
||||
}
|
||||
|
||||
if (itemsSpan.Length > 0)
|
||||
|
||||
@@ -22,21 +22,21 @@ namespace Recyclable.Collections
|
||||
|
||||
T[][] memoryBlocks = list._memoryBlocks;
|
||||
T[] currentBlock = memoryBlocks[targetBlockIndex];
|
||||
new Span<T>(currentBlock, targetItemIndex + 1, blockSizeMinus1 - targetItemIndex)
|
||||
new ReadOnlySpan<T>(currentBlock, targetItemIndex + 1, blockSizeMinus1 - targetItemIndex)
|
||||
.CopyTo(new Span<T>(currentBlock, targetItemIndex, blockSizeMinus1 - targetItemIndex));
|
||||
|
||||
while (targetBlockIndex < lastTakenBlockIndex)
|
||||
{
|
||||
new Span<T>(currentBlock)[blockSizeMinus1] = (currentBlock = memoryBlocks[++targetBlockIndex])[0];
|
||||
new Span<T>(currentBlock, 1, blockSizeMinus1)
|
||||
.CopyTo(new Span<T>(currentBlock));
|
||||
new ReadOnlySpan<T>(currentBlock, 1, blockSizeMinus1)
|
||||
.CopyTo(currentBlock);
|
||||
}
|
||||
|
||||
if (targetBlockIndex == lastTakenBlockIndex)
|
||||
{
|
||||
new Span<T>(currentBlock)[blockSizeMinus1] = (currentBlock = memoryBlocks[targetBlockIndex + 1])[0];
|
||||
new Span<T>(currentBlock, 1, list._nextItemIndex != 0 ? list._nextItemIndex - 1 : blockSizeMinus1)
|
||||
.CopyTo(new Span<T>(currentBlock));
|
||||
new ReadOnlySpan<T>(currentBlock, 1, list._nextItemIndex != 0 ? list._nextItemIndex - 1 : blockSizeMinus1)
|
||||
.CopyTo(currentBlock);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,12 +58,12 @@ namespace Recyclable.Collections
|
||||
int currentBlockIndex = lastTakenBlockIndex;
|
||||
while (currentBlockIndex > targetBlockIndex)
|
||||
{
|
||||
new Span<T>(currentBlock = memoryBlocks[currentBlockIndex--], 0, blockSizeMinus1)
|
||||
new ReadOnlySpan<T>(currentBlock = memoryBlocks[currentBlockIndex--], 0, blockSizeMinus1)
|
||||
.CopyTo(new Span<T>(currentBlock, 1, blockSizeMinus1));
|
||||
new Span<T>(currentBlock)[0] = memoryBlocks[currentBlockIndex][blockSizeMinus1];
|
||||
}
|
||||
|
||||
new Span<T>(currentBlock = memoryBlocks[targetBlockIndex], targetItemIndex, blockSizeMinus1 - targetItemIndex)
|
||||
new ReadOnlySpan<T>(currentBlock = memoryBlocks[targetBlockIndex], targetItemIndex, blockSizeMinus1 - targetItemIndex)
|
||||
.CopyTo(new Span<T>(currentBlock, targetItemIndex + 1, blockSizeMinus1 - targetItemIndex));
|
||||
|
||||
new Span<T>(memoryBlocks[targetBlockIndex])[targetItemIndex] = item;
|
||||
@@ -76,11 +76,12 @@ namespace Recyclable.Collections
|
||||
return;
|
||||
}
|
||||
|
||||
Span<T> sourceBlockMemory;
|
||||
ReadOnlySpan<T> sourceBlockMemory;
|
||||
Span<T> destinationArrayMemory;
|
||||
// TODO: Replace with bit-shifting
|
||||
int startingBlockIndex = (int)(startingIndex / blockSize);
|
||||
int lastBlockIndex = (int)((itemsCount / blockSize) + (itemsCount % blockSize != 0 ? 1 : 0)) - 1;
|
||||
Span<T[]> sourceMemoryBlocksSpan = new(sourceMemoryBlocks, startingBlockIndex, lastBlockIndex + 1);
|
||||
ReadOnlySpan<T[]> sourceMemoryBlocksSpan = new(sourceMemoryBlocks, startingBlockIndex, lastBlockIndex + 1);
|
||||
destinationArrayMemory = new Span<T>(destinationArray, destinationArrayIndex, (int)Math.Min(destinationArray.Length - destinationArrayIndex, itemsCount));
|
||||
int memoryBlockIndex;
|
||||
for (memoryBlockIndex = 0; memoryBlockIndex < lastBlockIndex; memoryBlockIndex++)
|
||||
@@ -104,11 +105,12 @@ namespace Recyclable.Collections
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Replace with bit-shifting
|
||||
int startingBlockIndex = (int)(startingIndex / blockSize);
|
||||
int lastBlockIndex = (int)((itemsCount / blockSize) + (itemsCount % blockSize != 0 ? 1 : 0)) - 1;
|
||||
|
||||
var destinationIndex = destinationArrayIndex;
|
||||
Span<T[]> sourceMemoryBlocksSpan = new(sourceMemoryBlocks, startingBlockIndex, lastBlockIndex + 1);
|
||||
ReadOnlySpan<T[]> sourceMemoryBlocksSpan = new(sourceMemoryBlocks, startingBlockIndex, lastBlockIndex + 1);
|
||||
for (int memoryBlockIndex = 0; memoryBlockIndex < lastBlockIndex; memoryBlockIndex++)
|
||||
{
|
||||
Array.ConstrainedCopy(sourceMemoryBlocksSpan[memoryBlockIndex], 0, destinationArray, destinationIndex, blockSize);
|
||||
@@ -192,7 +194,7 @@ namespace Recyclable.Collections
|
||||
}
|
||||
}
|
||||
|
||||
return checked(requiredBlockCount << minBlockSizePow2Shift);
|
||||
return requiredBlockCount << minBlockSizePow2Shift;
|
||||
}
|
||||
|
||||
#pragma warning disable CA2208
|
||||
|
||||
@@ -49,12 +49,12 @@ namespace Recyclable.Collections
|
||||
if (value is T typeValue)
|
||||
{
|
||||
Add(typeValue);
|
||||
return (int)(_longCount - 1);
|
||||
return checked((int)(_longCount - 1));
|
||||
}
|
||||
else if (value == null && _defaultIsNull)
|
||||
{
|
||||
Add(null);
|
||||
return (int)(_longCount - 1);
|
||||
return checked((int)(_longCount - 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace Recyclable.Collections
|
||||
long index = Array.IndexOf(list._memoryBlocks[blockIndex], itemToFind, 0, list._blockSize);
|
||||
if (index >= 0 && (!context._isItemFound || index < context.FoundItemIndex))
|
||||
{
|
||||
ExchangeFoundItemIndexIfLower(context, blockIndex, checked((long)blockIndex << list._blockSizePow2BitShift) + index);
|
||||
ExchangeFoundItemIndexIfLower(context, blockIndex, ((long)blockIndex << list._blockSizePow2BitShift) + index);
|
||||
return;
|
||||
}
|
||||
else if (context._isItemFound)
|
||||
@@ -41,7 +41,7 @@ namespace Recyclable.Collections
|
||||
index = Array.IndexOf(list._memoryBlocks[blockIndex + 1], itemToFind, 0, list._blockSize);
|
||||
if (index >= 0)
|
||||
{
|
||||
ExchangeFoundItemIndexIfLower(context, blockIndex + 1, checked((long)(blockIndex + 1) << list._blockSizePow2BitShift) + index);
|
||||
ExchangeFoundItemIndexIfLower(context, blockIndex + 1, ((long)(blockIndex + 1) << list._blockSizePow2BitShift) + index);
|
||||
return;
|
||||
}
|
||||
else if (context._isItemFound)
|
||||
@@ -56,7 +56,7 @@ namespace Recyclable.Collections
|
||||
index = Array.IndexOf(list._memoryBlocks[blockIndex + 2], itemToFind, 0, list._blockSize);
|
||||
if (index >= 0 && (!context._isItemFound || index < context.FoundItemIndex))
|
||||
{
|
||||
ExchangeFoundItemIndexIfLower(context, blockIndex + 2, checked((long)(blockIndex + 2) << list._blockSizePow2BitShift) + index);
|
||||
ExchangeFoundItemIndexIfLower(context, blockIndex + 2, ((long)(blockIndex + 2) << list._blockSizePow2BitShift) + index);
|
||||
return;
|
||||
}
|
||||
else if (context._isItemFound)
|
||||
@@ -71,7 +71,7 @@ namespace Recyclable.Collections
|
||||
index = Array.IndexOf(list._memoryBlocks[blockIndex + 3], itemToFind, 0, list._blockSize);
|
||||
if (!context._isItemFound && index >= 0)
|
||||
{
|
||||
ExchangeFoundItemIndexIfLower(context, blockIndex + 3, checked((long)(blockIndex + 3) << list._blockSizePow2BitShift) + index);
|
||||
ExchangeFoundItemIndexIfLower(context, blockIndex + 3, ((long)(blockIndex + 3) << list._blockSizePow2BitShift) + index);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -81,7 +81,7 @@ namespace Recyclable.Collections
|
||||
index = Array.IndexOf(list._memoryBlocks[blockIndex + 4], itemToFind, 0, list._blockSize);
|
||||
if (!context._isItemFound && index >= 0 && (!context._isItemFound || index < context.FoundItemIndex))
|
||||
{
|
||||
ExchangeFoundItemIndexIfLower(context, blockIndex + 4, checked((long)(blockIndex + 4) << list._blockSizePow2BitShift) + index);
|
||||
ExchangeFoundItemIndexIfLower(context, blockIndex + 4, ((long)(blockIndex + 4) << list._blockSizePow2BitShift) + index);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -91,7 +91,7 @@ namespace Recyclable.Collections
|
||||
index = Array.IndexOf(list._memoryBlocks[blockIndex + 5], itemToFind, 0, list._blockSize);
|
||||
if (!context._isItemFound && index >= 0 && (!context._isItemFound || index < context.FoundItemIndex))
|
||||
{
|
||||
ExchangeFoundItemIndexIfLower(context, blockIndex + 5, checked((long)(blockIndex + 5) << list._blockSizePow2BitShift) + index);
|
||||
ExchangeFoundItemIndexIfLower(context, blockIndex + 5, ((long)(blockIndex + 5) << list._blockSizePow2BitShift) + index);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -101,7 +101,7 @@ namespace Recyclable.Collections
|
||||
index = Array.IndexOf(list._memoryBlocks[blockIndex + 6], itemToFind, 0, list._blockSize);
|
||||
if (!context._isItemFound && index >= 0 && (!context._isItemFound || index < context.FoundItemIndex))
|
||||
{
|
||||
ExchangeFoundItemIndexIfLower(context, blockIndex + 6, checked((long)(blockIndex + 6) << list._blockSizePow2BitShift) + index);
|
||||
ExchangeFoundItemIndexIfLower(context, blockIndex + 6, ((long)(blockIndex + 6) << list._blockSizePow2BitShift) + index);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -111,7 +111,7 @@ namespace Recyclable.Collections
|
||||
index = Array.IndexOf(list._memoryBlocks[blockIndex + 7], itemToFind, 0, list._blockSize);
|
||||
if (!context._isItemFound && index >= 0 && (!context._isItemFound || index < context.FoundItemIndex))
|
||||
{
|
||||
ExchangeFoundItemIndexIfLower(context, blockIndex + 7, checked((long)(blockIndex + 7) << list._blockSizePow2BitShift) + index);
|
||||
ExchangeFoundItemIndexIfLower(context, blockIndex + 7, ((long)(blockIndex + 7) << list._blockSizePow2BitShift) + index);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -157,7 +157,7 @@ namespace Recyclable.Collections
|
||||
long index = Array.IndexOf(list._memoryBlocks[blockIndex], itemToFind, 0, list._blockSize);
|
||||
if (!context._isItemFound && index >= 0)
|
||||
{
|
||||
ExchangeFoundItemIndexIfLower(context, blockIndex, checked((long)blockIndex << list._blockSizePow2BitShift) + index);
|
||||
ExchangeFoundItemIndexIfLower(context, blockIndex, ((long)blockIndex << list._blockSizePow2BitShift) + index);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
@@ -214,7 +214,7 @@ namespace Recyclable.Collections
|
||||
// & WAS SLOWER
|
||||
// int blockSize = _blockSize;
|
||||
// & WAS SLOWER
|
||||
// while (checked((long)blockIndex << list._blockSizePow2BitShift) + itemIndex > step)
|
||||
// while (((long)blockIndex << list._blockSizePow2BitShift) + itemIndex > step)
|
||||
//long blockSize = checked((long)list._blockSize << 1);
|
||||
int lastBlockWithData = list._lastBlockWithData - BlocksForEachTask;
|
||||
while (blockIndex < lastBlockWithData)
|
||||
@@ -265,7 +265,7 @@ namespace Recyclable.Collections
|
||||
int itemIndex = Array.IndexOf(list._memoryBlocks[list._lastBlockWithData], item, 0, list._nextItemIndex > 0 ? list._nextItemIndex : list._blockSize);
|
||||
if (!context._isItemFound && itemIndex >= 0)
|
||||
{
|
||||
ExchangeFoundItemIndexIfLower(context, blockIndex, checked((long)blockIndex << list._blockSizePow2BitShift) + itemIndex);
|
||||
ExchangeFoundItemIndexIfLower(context, blockIndex, ((long)blockIndex << list._blockSizePow2BitShift) + itemIndex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -300,14 +300,14 @@ namespace Recyclable.Collections
|
||||
int itemIndex;
|
||||
// & WAS SLOWER
|
||||
//int lastBlockWithData = list._lastBlockWithData;
|
||||
Span<T[]> memoryBlocksSpan = new(list._memoryBlocks, 0, list._lastBlockWithData + 1);
|
||||
ReadOnlySpan<T[]> memoryBlocksSpan = new(list._memoryBlocks, 0, list._lastBlockWithData + 1);
|
||||
int blockIndex;
|
||||
for (blockIndex = 1; blockIndex < list._lastBlockWithData; blockIndex += 4)
|
||||
{
|
||||
itemIndex = Array.IndexOf(memoryBlocksSpan[blockIndex], item, 0, list._blockSize);
|
||||
if (itemIndex >= 0)
|
||||
{
|
||||
return itemIndex + checked((long)blockIndex << list._blockSizePow2BitShift);
|
||||
return itemIndex + (long)blockIndex << list._blockSizePow2BitShift;
|
||||
}
|
||||
|
||||
if (blockIndex + 1 < list._lastBlockWithData)
|
||||
@@ -315,7 +315,7 @@ namespace Recyclable.Collections
|
||||
itemIndex = Array.IndexOf(memoryBlocksSpan[blockIndex + 1], item, 0, list._blockSize);
|
||||
if (itemIndex >= 0)
|
||||
{
|
||||
return itemIndex + checked((long)(blockIndex + 1)<< list._blockSizePow2BitShift);
|
||||
return itemIndex + (long)(blockIndex + 1)<< list._blockSizePow2BitShift;
|
||||
}
|
||||
|
||||
if (blockIndex + 2 < list._lastBlockWithData)
|
||||
@@ -323,7 +323,7 @@ namespace Recyclable.Collections
|
||||
itemIndex = Array.IndexOf(memoryBlocksSpan[blockIndex + 2], item, 0, list._blockSize);
|
||||
if (itemIndex >= 0)
|
||||
{
|
||||
return itemIndex + checked((long)(blockIndex + 2)<< list._blockSizePow2BitShift);
|
||||
return itemIndex + (long)(blockIndex + 2)<< list._blockSizePow2BitShift;
|
||||
}
|
||||
|
||||
if (blockIndex + 3 < list._lastBlockWithData)
|
||||
@@ -331,7 +331,7 @@ namespace Recyclable.Collections
|
||||
itemIndex = Array.IndexOf(memoryBlocksSpan[blockIndex + 3], item, 0, list._blockSize);
|
||||
if (itemIndex >= 0)
|
||||
{
|
||||
return itemIndex + checked((long)(blockIndex + 3)<< list._blockSizePow2BitShift);
|
||||
return itemIndex + (long)(blockIndex + 3)<< list._blockSizePow2BitShift;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -342,7 +342,7 @@ namespace Recyclable.Collections
|
||||
? Array.IndexOf(memoryBlocksSpan[list._lastBlockWithData], item, 0, list._nextItemIndex)
|
||||
: Array.IndexOf(memoryBlocksSpan[list._lastBlockWithData], item, 0, list._blockSize);
|
||||
|
||||
return itemIndex >= 0 ? itemIndex + checked((long)list._lastBlockWithData << list._blockSizePow2BitShift) : RecyclableDefaults.ItemNotFoundIndexLong;
|
||||
return itemIndex >= 0 ? itemIndex + (long)list._lastBlockWithData << list._blockSizePow2BitShift : RecyclableDefaults.ItemNotFoundIndexLong;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -250,7 +250,7 @@ namespace Recyclable.Collections
|
||||
get => _memoryBlocks[index >> _blockSizePow2BitShift][index & _blockSizeMinus1];
|
||||
set
|
||||
{
|
||||
new Span<T>(_memoryBlocks[checked((int)(index >> _blockSizePow2BitShift))])[checked((int)(index & _blockSizeMinus1))] = value;
|
||||
new Span<T>(_memoryBlocks[(int)(index >> _blockSizePow2BitShift)])[(int)(index & _blockSizeMinus1)] = value;
|
||||
_version++;
|
||||
}
|
||||
}
|
||||
@@ -339,10 +339,10 @@ namespace Recyclable.Collections
|
||||
|
||||
if (_nextItemBlockIndex == 0 || (_nextItemIndex == 0 && _nextItemBlockIndex == 1))
|
||||
{
|
||||
return Array.IndexOf(_memoryBlocks[0], item, 0, checked((int)_longCount)) >= 0;
|
||||
return Array.IndexOf(_memoryBlocks[0], item, 0, (int)_longCount) >= 0;
|
||||
}
|
||||
|
||||
Span<T[]> memoryBlocksSpan = new(_memoryBlocks);
|
||||
ReadOnlySpan<T[]> memoryBlocksSpan = _memoryBlocks;
|
||||
int lastBlockIndex = _lastBlockWithData;
|
||||
for (int blockIndex = 0; blockIndex < lastBlockIndex; blockIndex++)
|
||||
{
|
||||
@@ -387,7 +387,7 @@ namespace Recyclable.Collections
|
||||
if (_longCount > _blockSize)
|
||||
{
|
||||
itemIndex = Array.IndexOf(_memoryBlocks[1], item, 0, (int)Math.Min(_blockSize, _longCount - _blockSize));
|
||||
return itemIndex >= 0 ? _blockSize + itemIndex : (int)IndexOfHelpers.IndexOfParallel(this, item);
|
||||
return itemIndex >= 0 ? _blockSize + itemIndex : checked((int)IndexOfHelpers.IndexOfParallel(this, item));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -18,28 +18,28 @@ namespace Recyclable.Collections
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static void CopyTo(RecyclableList<T[]> arrays, long startingIndex, int blockSize, int lastBlockSize, T[] destinationArray, int destinationArrayIndex)
|
||||
{
|
||||
Span<T> arrayMemory = destinationArray.AsSpan();
|
||||
Span<T> arrayMemory = destinationArray;
|
||||
arrayMemory = arrayMemory[destinationArrayIndex..];
|
||||
// TODO: Convert "/" & "%" to bit-shifting
|
||||
int startingArrayIndex = (int)(startingIndex / blockSize);
|
||||
startingIndex %= blockSize;
|
||||
if (arrays._count > 0)
|
||||
{
|
||||
ReadOnlySpan<T> sourceMemory = arrays[0].AsSpan();
|
||||
ReadOnlySpan<T> sourceMemory = arrays[0];
|
||||
var maxToCopy = (int)Math.Min(blockSize - startingIndex, arrayMemory.Length);
|
||||
if (arrays._count == 1)
|
||||
{
|
||||
maxToCopy = Math.Min(maxToCopy, lastBlockSize);
|
||||
}
|
||||
|
||||
sourceMemory = sourceMemory[(int)startingIndex..maxToCopy];
|
||||
sourceMemory = sourceMemory[checked((int)startingIndex)..maxToCopy];
|
||||
sourceMemory.CopyTo(arrayMemory);
|
||||
arrayMemory = arrayMemory[maxToCopy..];
|
||||
}
|
||||
|
||||
for (var arrayIdx = startingArrayIndex + 1; arrayIdx < arrays._count - 1 && arrayMemory.Length > 0; arrayIdx++)
|
||||
{
|
||||
ReadOnlySpan<T> sourceMemory = arrays[arrayIdx].AsSpan();
|
||||
ReadOnlySpan<T> sourceMemory = arrays[arrayIdx];
|
||||
var maxToCopy = Math.Min(blockSize, arrayMemory.Length);
|
||||
sourceMemory = sourceMemory[..maxToCopy];
|
||||
sourceMemory.CopyTo(arrayMemory);
|
||||
@@ -48,7 +48,7 @@ namespace Recyclable.Collections
|
||||
|
||||
if (arrays._count > 1 && arrayMemory.Length > 0)
|
||||
{
|
||||
ReadOnlySpan<T> sourceMemory = arrays[^1].AsSpan();
|
||||
ReadOnlySpan<T> sourceMemory = arrays[^1];
|
||||
var maxToCopy = Math.Min(lastBlockSize, arrayMemory.Length);
|
||||
sourceMemory = sourceMemory[..maxToCopy];
|
||||
sourceMemory.CopyTo(arrayMemory);
|
||||
@@ -94,7 +94,7 @@ namespace Recyclable.Collections
|
||||
for (var arrayIdx = 0; arrayIdx < arrays._count; arrayIdx++)
|
||||
{
|
||||
var array = arrays[arrayIdx];
|
||||
Span<T> arrayMemory = array.AsSpan();
|
||||
ReadOnlySpan<T> arrayMemory = array;
|
||||
for (int memoryIdx = 0; memoryIdx < arrayMemory.Length; memoryIdx++)
|
||||
{
|
||||
if (comparer.Equals(arrayMemory[memoryIdx], item))
|
||||
|
||||
@@ -76,7 +76,7 @@ namespace Recyclable.Collections
|
||||
|
||||
public int Count
|
||||
{
|
||||
get => (int)LongCount;
|
||||
get => checked((int)LongCount);
|
||||
set => LongCount = value;
|
||||
}
|
||||
|
||||
@@ -167,11 +167,11 @@ namespace Recyclable.Collections
|
||||
|
||||
#pragma warning disable CS0618
|
||||
public bool Contains(T item) => RecyclableQueueHelpers<T>.Contains(Memory, item);
|
||||
public void CopyTo(T[] array, int arrayIndex) => RecyclableQueueHelpers<T>.CopyTo(Memory, RemovedCount, BlockSize, (int)(LongCount % BlockSize), array, arrayIndex);
|
||||
public void CopyTo(T[] array, int arrayIndex) => RecyclableQueueHelpers<T>.CopyTo(Memory, RemovedCount, BlockSize, checked((int)(LongCount % BlockSize)), array, arrayIndex);
|
||||
public IEnumerable<T> Enumerate() => RecyclableQueueHelpers<T>.Enumerate(Memory, BlockSize, LongCount);
|
||||
public IEnumerator<T> GetEnumerator() => RecyclableQueueHelpers<T>.Enumerate(Memory, BlockSize, LongCount).GetEnumerator();
|
||||
IEnumerator IEnumerable.GetEnumerator() => RecyclableQueueHelpers<T>.Enumerate(Memory, BlockSize, LongCount).GetEnumerator();
|
||||
public int IndexOf(T item) => (int)GetRelativeIndex(RecyclableQueueHelpers<T>.LongIndexOf(Memory, BlockSize, item, _equalityComparer));
|
||||
public int IndexOf(T item) => checked((int)GetRelativeIndex(RecyclableQueueHelpers<T>.LongIndexOf(Memory, BlockSize, item, _equalityComparer)));
|
||||
public long LongIndexOf(T item) => GetRelativeIndex(RecyclableQueueHelpers<T>.LongIndexOf(Memory, BlockSize, item, _equalityComparer));
|
||||
#pragma warning restore CS0618
|
||||
|
||||
|
||||
Reference in new issue
Block a user