"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:
mlemanczyk committed 2023-10-08 19:01:26 +02:00
1 parent 39d63d1d65
commit d4d1364628
16 files changed
+204 -137

No files matched your search

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