diff --git a/Recyclable.Collections/RecyclableList.Enumerator.cs b/Recyclable.Collections/RecyclableList.Enumerator.cs index acaae28..7a0b603 100644 --- a/Recyclable.Collections/RecyclableList.Enumerator.cs +++ b/Recyclable.Collections/RecyclableList.Enumerator.cs @@ -6,9 +6,10 @@ namespace Recyclable.Collections { public partial class RecyclableList { - [StructLayout(LayoutKind.Sequential, Pack = 1)] - public struct Enumerator : IEnumerator - { + [StructLayout(LayoutKind.Sequential, Pack = 1)] + [VersionedCollectionsGenerator.CloneForVersioned] + public struct Enumerator : IEnumerator + { private static readonly bool _isReferenceType = !typeof(T).IsValueType; private int _currentItemIndex; diff --git a/Recyclable.Collections/RecyclableList.Extensions.cs b/Recyclable.Collections/RecyclableList.Extensions.cs index d10ac29..bf55211 100644 --- a/Recyclable.Collections/RecyclableList.Extensions.cs +++ b/Recyclable.Collections/RecyclableList.Extensions.cs @@ -3,8 +3,9 @@ using System.Runtime.CompilerServices; namespace Recyclable.Collections { - public static class RecyclableListExtensions - { + [VersionedCollectionsGenerator.GenerateVersioned] + public static class RecyclableListExtensions + { [MethodImpl(MethodImplOptions.AggressiveInlining)] public static RecyclableList ToRecyclableList(this Array values) => new(values); diff --git a/Recyclable.Collections/RecyclableList.VersionedEnumerator.cs b/Recyclable.Collections/RecyclableList.VersionedEnumerator.cs index 5e729f7..2623ebd 100644 --- a/Recyclable.Collections/RecyclableList.VersionedEnumerator.cs +++ b/Recyclable.Collections/RecyclableList.VersionedEnumerator.cs @@ -6,11 +6,13 @@ namespace Recyclable.Collections { public partial class RecyclableList : IRecyclableVersionedList { - VersionedEnumerator IRecyclableVersionedList.GetEnumerator() => new(this); + [VersionedCollectionsGenerator.CloneForVersioned] + VersionedEnumerator IRecyclableVersionedList.GetEnumerator() => new(this); - [StructLayout(LayoutKind.Sequential, Pack = 1)] - public struct VersionedEnumerator : IEnumerator - { + [StructLayout(LayoutKind.Sequential, Pack = 1)] + [VersionedCollectionsGenerator.CloneForVersioned] + public struct VersionedEnumerator : IEnumerator + { private int _currentItemIndex; private readonly ulong _enumeratorVersion; private readonly RecyclableList _list; diff --git a/Recyclable.Collections/RecyclableList.cs b/Recyclable.Collections/RecyclableList.cs index 5a46ab2..8f068dc 100644 --- a/Recyclable.Collections/RecyclableList.cs +++ b/Recyclable.Collections/RecyclableList.cs @@ -363,14 +363,29 @@ namespace Recyclable.Collections #endif } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Enumerator GetEnumerator() => new(this); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [VersionedCollectionsGenerator.CloneForVersioned] +#if WITH_VERSIONING + public VersionedEnumerator GetEnumerator() => new(this); +#else + public Enumerator GetEnumerator() => new(this); +#endif - [MethodImpl(MethodImplOptions.AggressiveInlining)] - IEnumerator IEnumerable.GetEnumerator() => new Enumerator(this); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [VersionedCollectionsGenerator.CloneForVersioned] +#if WITH_VERSIONING + IEnumerator IEnumerable.GetEnumerator() => new VersionedEnumerator(this); +#else + IEnumerator IEnumerable.GetEnumerator() => new Enumerator(this); +#endif - [MethodImpl(MethodImplOptions.AggressiveInlining)] - IEnumerator IEnumerable.GetEnumerator() => new Enumerator(this); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [VersionedCollectionsGenerator.CloneForVersioned] +#if WITH_VERSIONING + IEnumerator IEnumerable.GetEnumerator() => new VersionedEnumerator(this); +#else + IEnumerator IEnumerable.GetEnumerator() => new Enumerator(this); +#endif public void Dispose() { diff --git a/Recyclable.Collections/RecyclableLongList.Enumerator.cs b/Recyclable.Collections/RecyclableLongList.Enumerator.cs index 353f2d3..b8100c7 100644 --- a/Recyclable.Collections/RecyclableLongList.Enumerator.cs +++ b/Recyclable.Collections/RecyclableLongList.Enumerator.cs @@ -5,8 +5,9 @@ namespace Recyclable.Collections { public partial class RecyclableLongList { - public struct Enumerator : IEnumerator - { + [VersionedCollectionsGenerator.CloneForVersioned] + public struct Enumerator : IEnumerator + { #nullable disable private static readonly T _default = default; #nullable restore diff --git a/Recyclable.Collections/RecyclableLongList.Extensions.cs b/Recyclable.Collections/RecyclableLongList.Extensions.cs index 5f24356..fc89683 100644 --- a/Recyclable.Collections/RecyclableLongList.Extensions.cs +++ b/Recyclable.Collections/RecyclableLongList.Extensions.cs @@ -3,8 +3,9 @@ using System.Runtime.CompilerServices; namespace Recyclable.Collections { - public static class RecyclableLongListExtensions - { + [VersionedCollectionsGenerator.GenerateVersioned] + public static class RecyclableLongListExtensions + { [MethodImpl(MethodImplOptions.AggressiveInlining)] public static RecyclableLongList ToRecyclableLongList(this Array values, int minBlockSize = RecyclableDefaults.BlockSize) => new(values, minBlockSize); diff --git a/Recyclable.Collections/RecyclableLongList.Helpers.cs b/Recyclable.Collections/RecyclableLongList.Helpers.cs index 6015f77..61dc9d7 100644 --- a/Recyclable.Collections/RecyclableLongList.Helpers.cs +++ b/Recyclable.Collections/RecyclableLongList.Helpers.cs @@ -1,4 +1,5 @@ using Recyclable.Collections.Pools; +using System.Numerics; using System.Runtime.CompilerServices; namespace Recyclable.Collections @@ -76,11 +77,11 @@ namespace Recyclable.Collections return; } - ReadOnlySpan sourceBlockMemory; - Span destinationArrayMemory; - // TODO: Replace with bit-shifting - int startingBlockIndex = (int)(startingIndex / blockSize); - int lastBlockIndex = (int)((itemsCount / blockSize) + (itemsCount % blockSize != 0 ? 1 : 0)) - 1; + ReadOnlySpan sourceBlockMemory; + Span destinationArrayMemory; + int blockSizePow2Shift = BitOperations.TrailingZeroCount((uint)blockSize); + int startingBlockIndex = (int)(startingIndex >> blockSizePow2Shift); + int lastBlockIndex = (int)((itemsCount >> blockSizePow2Shift) + ((itemsCount & (blockSize - 1)) != 0 ? 1 : 0)) - 1; ReadOnlySpan sourceMemoryBlocksSpan = new(sourceMemoryBlocks, startingBlockIndex, lastBlockIndex + 1); destinationArrayMemory = new Span(destinationArray, destinationArrayIndex, (int)Math.Min(destinationArray.Length - destinationArrayIndex, itemsCount)); int memoryBlockIndex; @@ -105,9 +106,9 @@ 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; + int blockSizePow2Shift = BitOperations.TrailingZeroCount((uint)blockSize); + int startingBlockIndex = (int)(startingIndex >> blockSizePow2Shift); + int lastBlockIndex = (int)((itemsCount >> blockSizePow2Shift) + ((itemsCount & (blockSize - 1)) != 0 ? 1 : 0)) - 1; var destinationIndex = destinationArrayIndex; ReadOnlySpan sourceMemoryBlocksSpan = new(sourceMemoryBlocks, startingBlockIndex, lastBlockIndex + 1); diff --git a/Recyclable.Collections/RecyclableLongList.VersionedEnumerator.cs b/Recyclable.Collections/RecyclableLongList.VersionedEnumerator.cs index ad86d10..cbb3e92 100644 --- a/Recyclable.Collections/RecyclableLongList.VersionedEnumerator.cs +++ b/Recyclable.Collections/RecyclableLongList.VersionedEnumerator.cs @@ -5,11 +5,14 @@ namespace Recyclable.Collections { public partial class RecyclableLongList : IRecyclableVersionedLongList { - public VersionedEnumerator GetVersionedEnumerator() => new(this); - VersionedEnumerator IRecyclableVersionedLongList.GetEnumerator() => new(this); + [VersionedCollectionsGenerator.CloneForVersioned] + public VersionedEnumerator GetVersionedEnumerator() => new(this); + [VersionedCollectionsGenerator.CloneForVersioned] + VersionedEnumerator IRecyclableVersionedLongList.GetEnumerator() => new(this); - public struct VersionedEnumerator : IEnumerator - { + [VersionedCollectionsGenerator.CloneForVersioned] + public struct VersionedEnumerator : IEnumerator + { #nullable disable private static readonly T _default = default; #nullable restore diff --git a/Recyclable.Collections/RecyclableLongList.cs b/Recyclable.Collections/RecyclableLongList.cs index c9b574b..a0ebb71 100644 --- a/Recyclable.Collections/RecyclableLongList.cs +++ b/Recyclable.Collections/RecyclableLongList.cs @@ -372,9 +372,24 @@ namespace Recyclable.Collections public void CopyTo(T[] array, int arrayIndex) => Helpers.CopyTo(_memoryBlocks, 0, _blockSize, _longCount, array, arrayIndex); - public Enumerator GetEnumerator() => new(this); - IEnumerator IEnumerable.GetEnumerator() => new Enumerator(this); - IEnumerator IEnumerable.GetEnumerator() => new Enumerator(this); + [VersionedCollectionsGenerator.CloneForVersioned] +#if WITH_VERSIONING + public VersionedEnumerator GetEnumerator() => new(this); +#else + public Enumerator GetEnumerator() => new(this); +#endif + [VersionedCollectionsGenerator.CloneForVersioned] +#if WITH_VERSIONING + IEnumerator IEnumerable.GetEnumerator() => new VersionedEnumerator(this); +#else + IEnumerator IEnumerable.GetEnumerator() => new Enumerator(this); +#endif + [VersionedCollectionsGenerator.CloneForVersioned] +#if WITH_VERSIONING + IEnumerator IEnumerable.GetEnumerator() => new VersionedEnumerator(this); +#else + IEnumerator IEnumerable.GetEnumerator() => new Enumerator(this); +#endif [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public int IndexOf(T item)