Add optimized AddRange overloads for recyclable collections
This commit is contained in:
1 parent
e1298c817d
commit
f4e2285734
10 files changed
+723
-84
No files matched your search
@@ -9,20 +9,20 @@ namespace Recyclable.Collections
|
|||||||
internal sealed class RecyclableDictionary<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>>, IDisposable
|
internal sealed class RecyclableDictionary<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>>, IDisposable
|
||||||
where TKey : notnull
|
where TKey : notnull
|
||||||
{
|
{
|
||||||
private static readonly bool _needsClearing = !typeof(TKey).IsValueType || !typeof(TValue).IsValueType;
|
internal static readonly bool _needsClearing = !typeof(TKey).IsValueType || !typeof(TValue).IsValueType;
|
||||||
|
|
||||||
private readonly int _blockSize;
|
internal readonly int _blockSize;
|
||||||
private readonly int _blockSizeMinus1;
|
internal readonly int _blockSizeMinus1;
|
||||||
private readonly byte _blockShift;
|
internal readonly byte _blockShift;
|
||||||
|
|
||||||
#nullable disable
|
#nullable disable
|
||||||
private Entry[][] _entries;
|
internal Entry[][] _entries;
|
||||||
#nullable restore
|
#nullable restore
|
||||||
private int[] _buckets;
|
internal int[] _buckets;
|
||||||
private int _count;
|
internal int _count;
|
||||||
private bool _disposed;
|
internal bool _disposed;
|
||||||
|
|
||||||
private struct Entry
|
internal struct Entry
|
||||||
{
|
{
|
||||||
public int HashCode;
|
public int HashCode;
|
||||||
public int Next;
|
public int Next;
|
||||||
|
|||||||
@@ -9,20 +9,20 @@ namespace Recyclable.Collections
|
|||||||
internal sealed class RecyclableHashSet<T> : IEnumerable<T>, IDisposable
|
internal sealed class RecyclableHashSet<T> : IEnumerable<T>, IDisposable
|
||||||
where T : notnull
|
where T : notnull
|
||||||
{
|
{
|
||||||
private static readonly bool _needsClearing = !typeof(T).IsValueType;
|
internal static readonly bool _needsClearing = !typeof(T).IsValueType;
|
||||||
|
|
||||||
private readonly int _blockSize;
|
internal readonly int _blockSize;
|
||||||
private readonly int _blockSizeMinus1;
|
internal readonly int _blockSizeMinus1;
|
||||||
private readonly byte _blockShift;
|
internal readonly byte _blockShift;
|
||||||
|
|
||||||
#nullable disable
|
#nullable disable
|
||||||
private Entry[][] _entries;
|
internal Entry[][] _entries;
|
||||||
#nullable restore
|
#nullable restore
|
||||||
private int[] _buckets;
|
internal int[] _buckets;
|
||||||
private int _count;
|
internal int _count;
|
||||||
private bool _disposed;
|
internal bool _disposed;
|
||||||
|
|
||||||
private struct Entry
|
internal struct Entry
|
||||||
{
|
{
|
||||||
public int HashCode;
|
public int HashCode;
|
||||||
public int Next;
|
public int Next;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ namespace Recyclable.Collections
|
|||||||
{
|
{
|
||||||
internal sealed class RecyclableLinkedList<T> : IEnumerable<T>, IDisposable
|
internal sealed class RecyclableLinkedList<T> : IEnumerable<T>, IDisposable
|
||||||
{
|
{
|
||||||
private static readonly bool _needsClearing = !typeof(T).IsValueType;
|
internal static readonly bool _needsClearing = !typeof(T).IsValueType;
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private static BiDirectionalRecyclableArrayPoolChunk<T> RentChunk(int size, BiDirectionalRecyclableArrayPoolChunk<T>? previous, bool forHead)
|
private static BiDirectionalRecyclableArrayPoolChunk<T> RentChunk(int size, BiDirectionalRecyclableArrayPoolChunk<T>? previous, bool forHead)
|
||||||
@@ -53,11 +53,11 @@ namespace Recyclable.Collections
|
|||||||
BiDirectionalRecyclableArrayPoolChunkPool<T>.Dispose(chunk, _needsClearing);
|
BiDirectionalRecyclableArrayPoolChunkPool<T>.Dispose(chunk, _needsClearing);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BiDirectionalRecyclableArrayPoolChunk<T> _head;
|
internal BiDirectionalRecyclableArrayPoolChunk<T> _head;
|
||||||
private BiDirectionalRecyclableArrayPoolChunk<T> _tail;
|
internal BiDirectionalRecyclableArrayPoolChunk<T> _tail;
|
||||||
private bool _disposed;
|
internal bool _disposed;
|
||||||
private long _capacity;
|
internal long _capacity;
|
||||||
private long _count;
|
internal long _count;
|
||||||
|
|
||||||
public RecyclableLinkedList(int initialCapacity = RecyclableDefaults.InitialCapacity)
|
public RecyclableLinkedList(int initialCapacity = RecyclableDefaults.InitialCapacity)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -162,12 +162,12 @@ namespace Recyclable.Collections
|
|||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
public static void AddRange<T>(this RecyclableList<T> list, RecyclableLongList<T> items)
|
public static void AddRange<T>(this RecyclableList<T> list, RecyclableLongList<T> items)
|
||||||
{
|
{
|
||||||
if (items._longCount == 0)
|
if (items._longCount == 0)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int oldCount = list._count;
|
int oldCount = list._count;
|
||||||
long sourceItemsCount = items._longCount;
|
long sourceItemsCount = items._longCount;
|
||||||
@@ -208,9 +208,263 @@ namespace Recyclable.Collections
|
|||||||
itemsSpan.CopyTo(targetSpan);
|
itemsSpan.CopyTo(targetSpan);
|
||||||
}
|
}
|
||||||
|
|
||||||
list._count = targetCapacity;
|
list._count = targetCapacity;
|
||||||
list._version++;
|
list._version++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
|
internal static void AddRange<T>(this RecyclableList<T> list, RecyclableHashSet<T> items)
|
||||||
|
{
|
||||||
|
if (items._count == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int oldCount = list._count,
|
||||||
|
sourceCount = items._count,
|
||||||
|
targetCapacity = oldCount + sourceCount;
|
||||||
|
|
||||||
|
if (list._capacity < targetCapacity)
|
||||||
|
{
|
||||||
|
list._capacity = RecyclableListHelpers<T>.EnsureCapacity(list, oldCount, checked((int)BitOperations.RoundUpToPowerOf2((uint)targetCapacity)));
|
||||||
|
}
|
||||||
|
|
||||||
|
Span<T> targetSpan = new(list._memoryBlock, oldCount, sourceCount);
|
||||||
|
var entries = items._entries;
|
||||||
|
int shift = items._blockShift,
|
||||||
|
mask = items._blockSizeMinus1;
|
||||||
|
|
||||||
|
for (int i = 0; i < sourceCount; i++)
|
||||||
|
{
|
||||||
|
targetSpan[i] = entries[i >> shift][i & mask].Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
list._count = targetCapacity;
|
||||||
|
list._version++;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
|
internal static void AddRange<T>(this RecyclableList<T> list, RecyclableStack<T> items)
|
||||||
|
{
|
||||||
|
if (items._count == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (items._count > int.MaxValue - list._count)
|
||||||
|
{
|
||||||
|
ThrowHelper.ThrowArgumentOutOfRangeException(nameof(items), "The total number of items exceeds the capacity of RecyclableList.");
|
||||||
|
}
|
||||||
|
|
||||||
|
int oldCount = list._count,
|
||||||
|
sourceCount = checked((int)items._count),
|
||||||
|
targetCapacity = oldCount + sourceCount;
|
||||||
|
|
||||||
|
if (list._capacity < targetCapacity)
|
||||||
|
{
|
||||||
|
list._capacity = RecyclableListHelpers<T>.EnsureCapacity(list, oldCount, checked((int)BitOperations.RoundUpToPowerOf2((uint)targetCapacity)));
|
||||||
|
}
|
||||||
|
|
||||||
|
Span<T> targetSpan = new(list._memoryBlock, oldCount, sourceCount);
|
||||||
|
int index = 0;
|
||||||
|
var chunk = items._current;
|
||||||
|
while (chunk != null)
|
||||||
|
{
|
||||||
|
var array = chunk.Value;
|
||||||
|
for (int i = chunk.Index - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
targetSpan[index++] = array[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
chunk = chunk.Previous;
|
||||||
|
}
|
||||||
|
|
||||||
|
list._count = targetCapacity;
|
||||||
|
list._version++;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
|
internal static void AddRange<T>(this RecyclableList<T> list, RecyclableSortedSet<T> items)
|
||||||
|
{
|
||||||
|
if (items._count == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int oldCount = list._count,
|
||||||
|
sourceCount = items._count,
|
||||||
|
targetCapacity = oldCount + sourceCount;
|
||||||
|
|
||||||
|
if (list._capacity < targetCapacity)
|
||||||
|
{
|
||||||
|
list._capacity = RecyclableListHelpers<T>.EnsureCapacity(list, oldCount, checked((int)BitOperations.RoundUpToPowerOf2((uint)targetCapacity)));
|
||||||
|
}
|
||||||
|
|
||||||
|
new ReadOnlySpan<T>(items._items, 0, sourceCount).CopyTo(new Span<T>(list._memoryBlock, oldCount, sourceCount));
|
||||||
|
|
||||||
|
list._count = targetCapacity;
|
||||||
|
list._version++;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
|
internal static void AddRange<T>(this RecyclableList<T> list, RecyclableLinkedList<T> items)
|
||||||
|
{
|
||||||
|
if (items._count == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (items._count > int.MaxValue - list._count)
|
||||||
|
{
|
||||||
|
ThrowHelper.ThrowArgumentOutOfRangeException(nameof(items), "The total number of items exceeds the capacity of RecyclableList.");
|
||||||
|
}
|
||||||
|
|
||||||
|
int oldCount = list._count,
|
||||||
|
sourceCount = checked((int)items._count),
|
||||||
|
targetCapacity = oldCount + sourceCount;
|
||||||
|
|
||||||
|
if (list._capacity < targetCapacity)
|
||||||
|
{
|
||||||
|
list._capacity = RecyclableListHelpers<T>.EnsureCapacity(list, oldCount, checked((int)BitOperations.RoundUpToPowerOf2((uint)targetCapacity)));
|
||||||
|
}
|
||||||
|
|
||||||
|
Span<T> targetSpan = new(list._memoryBlock, oldCount, sourceCount);
|
||||||
|
int index = 0;
|
||||||
|
var chunk = items._head;
|
||||||
|
while (chunk != null)
|
||||||
|
{
|
||||||
|
for (int i = chunk.Bottom; i < chunk.Top; i++)
|
||||||
|
{
|
||||||
|
targetSpan[index++] = chunk.Value[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
chunk = chunk.Next;
|
||||||
|
}
|
||||||
|
|
||||||
|
list._count = targetCapacity;
|
||||||
|
list._version++;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
|
internal static void AddRange<T>(this RecyclableList<T> list, RecyclablePriorityQueue<T> items)
|
||||||
|
{
|
||||||
|
if (items._size == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int oldCount = list._count,
|
||||||
|
sourceCount = items._size,
|
||||||
|
targetCapacity = oldCount + sourceCount;
|
||||||
|
|
||||||
|
if (list._capacity < targetCapacity)
|
||||||
|
{
|
||||||
|
list._capacity = RecyclableListHelpers<T>.EnsureCapacity(list, oldCount, checked((int)BitOperations.RoundUpToPowerOf2((uint)targetCapacity)));
|
||||||
|
}
|
||||||
|
|
||||||
|
new ReadOnlySpan<T>(items._heap, 0, sourceCount).CopyTo(new Span<T>(list._memoryBlock, oldCount, sourceCount));
|
||||||
|
|
||||||
|
list._count = targetCapacity;
|
||||||
|
list._version++;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
|
internal static void AddRange<T>(this RecyclableList<T> list, RecyclableQueue<T> items)
|
||||||
|
{
|
||||||
|
if (items._count == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (items._count > int.MaxValue - list._count)
|
||||||
|
{
|
||||||
|
ThrowHelper.ThrowArgumentOutOfRangeException(nameof(items), "The total number of items exceeds the capacity of RecyclableList.");
|
||||||
|
}
|
||||||
|
|
||||||
|
int oldCount = list._count,
|
||||||
|
sourceCount = checked((int)items._count),
|
||||||
|
targetCapacity = oldCount + sourceCount;
|
||||||
|
|
||||||
|
if (list._capacity < targetCapacity)
|
||||||
|
{
|
||||||
|
list._capacity = RecyclableListHelpers<T>.EnsureCapacity(list, oldCount, checked((int)BitOperations.RoundUpToPowerOf2((uint)targetCapacity)));
|
||||||
|
}
|
||||||
|
|
||||||
|
Span<T> targetSpan = new(list._memoryBlock, oldCount, sourceCount);
|
||||||
|
int index = 0;
|
||||||
|
var chunk = items._head;
|
||||||
|
while (chunk != null)
|
||||||
|
{
|
||||||
|
for (int i = chunk.Bottom; i < chunk.Top; i++)
|
||||||
|
{
|
||||||
|
targetSpan[index++] = chunk.Value[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
chunk = chunk.Next;
|
||||||
|
}
|
||||||
|
|
||||||
|
list._count = targetCapacity;
|
||||||
|
list._version++;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
|
internal static void AddRange<TKey, TValue>(this RecyclableList<KeyValuePair<TKey, TValue>> list, RecyclableDictionary<TKey, TValue> items)
|
||||||
|
{
|
||||||
|
if (items._count == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int oldCount = list._count,
|
||||||
|
sourceCount = items._count,
|
||||||
|
targetCapacity = oldCount + sourceCount;
|
||||||
|
|
||||||
|
if (list._capacity < targetCapacity)
|
||||||
|
{
|
||||||
|
list._capacity = RecyclableListHelpers<KeyValuePair<TKey, TValue>>.EnsureCapacity(list, oldCount, checked((int)BitOperations.RoundUpToPowerOf2((uint)targetCapacity)));
|
||||||
|
}
|
||||||
|
|
||||||
|
Span<KeyValuePair<TKey, TValue>> targetSpan = new(list._memoryBlock, oldCount, sourceCount);
|
||||||
|
var entries = items._entries;
|
||||||
|
int shift = items._blockShift,
|
||||||
|
mask = items._blockSizeMinus1;
|
||||||
|
|
||||||
|
for (int i = 0; i < sourceCount; i++)
|
||||||
|
{
|
||||||
|
ref var entry = ref entries[i >> shift][i & mask];
|
||||||
|
targetSpan[i] = new KeyValuePair<TKey, TValue>(entry.Key, entry.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
list._count = targetCapacity;
|
||||||
|
list._version++;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
|
internal static void AddRange<TKey, TValue>(this RecyclableList<(TKey Key, TValue Value)> list, RecyclableSortedList<TKey, TValue> items)
|
||||||
|
{
|
||||||
|
if (items._count == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int oldCount = list._count,
|
||||||
|
sourceCount = items._count,
|
||||||
|
targetCapacity = oldCount + sourceCount;
|
||||||
|
|
||||||
|
if (list._capacity < targetCapacity)
|
||||||
|
{
|
||||||
|
list._capacity = RecyclableListHelpers<(TKey Key, TValue Value)>.EnsureCapacity(list, oldCount, checked((int)BitOperations.RoundUpToPowerOf2((uint)targetCapacity)));
|
||||||
|
}
|
||||||
|
|
||||||
|
Span<(TKey Key, TValue Value)> targetSpan = new(list._memoryBlock, oldCount, sourceCount);
|
||||||
|
for (int i = 0; i < sourceCount; i++)
|
||||||
|
{
|
||||||
|
targetSpan[i] = (items._keys[i], items._values[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
list._count = targetCapacity;
|
||||||
|
list._version++;
|
||||||
|
}
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
@@ -291,15 +545,39 @@ namespace Recyclable.Collections
|
|||||||
{
|
{
|
||||||
AddRange(list, sourceList);
|
AddRange(list, sourceList);
|
||||||
}
|
}
|
||||||
else if (items is ICollection<T> sourceICollection)
|
else if (items is ICollection<T> sourceICollection)
|
||||||
{
|
{
|
||||||
AddRange(list, sourceICollection);
|
AddRange(list, sourceICollection);
|
||||||
}
|
}
|
||||||
else if (items is ICollection sourceICollectionWithObjects)
|
else if (items is ICollection sourceICollectionWithObjects)
|
||||||
{
|
{
|
||||||
AddRange(list, sourceICollectionWithObjects);
|
AddRange(list, sourceICollectionWithObjects);
|
||||||
}
|
}
|
||||||
else if (items is IReadOnlyList<T> sourceIReadOnlyList)
|
else if (items is RecyclableHashSet<T> sourceHashSet)
|
||||||
|
{
|
||||||
|
AddRange(list, sourceHashSet);
|
||||||
|
}
|
||||||
|
else if (items is RecyclableStack<T> sourceStack)
|
||||||
|
{
|
||||||
|
AddRange(list, sourceStack);
|
||||||
|
}
|
||||||
|
else if (items is RecyclableSortedSet<T> sourceSortedSet)
|
||||||
|
{
|
||||||
|
AddRange(list, sourceSortedSet);
|
||||||
|
}
|
||||||
|
else if (items is RecyclableLinkedList<T> sourceLinkedList)
|
||||||
|
{
|
||||||
|
AddRange(list, sourceLinkedList);
|
||||||
|
}
|
||||||
|
else if (items is RecyclablePriorityQueue<T> sourcePriorityQueue)
|
||||||
|
{
|
||||||
|
AddRange(list, sourcePriorityQueue);
|
||||||
|
}
|
||||||
|
else if (items is RecyclableQueue<T> sourceQueue)
|
||||||
|
{
|
||||||
|
AddRange(list, sourceQueue);
|
||||||
|
}
|
||||||
|
else if (items is IReadOnlyList<T> sourceIReadOnlyList)
|
||||||
{
|
{
|
||||||
AddRange(list, sourceIReadOnlyList);
|
AddRange(list, sourceIReadOnlyList);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
using Recyclable.Collections.Pools;
|
using Recyclable.Collections.Pools;
|
||||||
|
|
||||||
namespace Recyclable.Collections
|
namespace Recyclable.Collections
|
||||||
@@ -405,13 +406,37 @@ namespace Recyclable.Collections
|
|||||||
targetList.AddRange(sourceICollection);
|
targetList.AddRange(sourceICollection);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case ICollection sourceICollectionWithObjects:
|
case ICollection sourceICollectionWithObjects:
|
||||||
targetList.AddRange(sourceICollectionWithObjects);
|
targetList.AddRange(sourceICollectionWithObjects);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case IReadOnlyList<T> sourceIReadOnlyList:
|
case IReadOnlyList<T> sourceIReadOnlyList:
|
||||||
targetList.AddRange(sourceIReadOnlyList);
|
targetList.AddRange(sourceIReadOnlyList);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
case RecyclableHashSet<T> sourceHashSet:
|
||||||
|
targetList.AddRange(sourceHashSet);
|
||||||
|
return;
|
||||||
|
|
||||||
|
case RecyclableStack<T> sourceStack:
|
||||||
|
targetList.AddRange(sourceStack);
|
||||||
|
return;
|
||||||
|
|
||||||
|
case RecyclableSortedSet<T> sourceSortedSet:
|
||||||
|
targetList.AddRange(sourceSortedSet);
|
||||||
|
return;
|
||||||
|
|
||||||
|
case RecyclableLinkedList<T> sourceLinkedList:
|
||||||
|
targetList.AddRange(sourceLinkedList);
|
||||||
|
return;
|
||||||
|
|
||||||
|
case RecyclablePriorityQueue<T> sourcePriorityQueue:
|
||||||
|
targetList.AddRange(sourcePriorityQueue);
|
||||||
|
return;
|
||||||
|
|
||||||
|
case RecyclableQueue<T> sourceQueue:
|
||||||
|
targetList.AddRange(sourceQueue);
|
||||||
|
return;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (items.TryGetNonEnumeratedCount(out var requiredAdditionalCapacity))
|
if (items.TryGetNonEnumeratedCount(out var requiredAdditionalCapacity))
|
||||||
@@ -760,12 +785,12 @@ namespace Recyclable.Collections
|
|||||||
targetList._version++;
|
targetList._version++;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void AddRange<T>(this RecyclableLongList<T> targetList, in T[] items)
|
public static void AddRange<T>(this RecyclableLongList<T> targetList, in T[] items)
|
||||||
{
|
{
|
||||||
if (items.LongLength == 0)
|
if (items.LongLength == 0)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int targetBlockIndex = targetList._nextItemBlockIndex;
|
int targetBlockIndex = targetList._nextItemBlockIndex;
|
||||||
|
|
||||||
@@ -812,8 +837,344 @@ namespace Recyclable.Collections
|
|||||||
}
|
}
|
||||||
|
|
||||||
targetList._longCount = targetCapacity;
|
targetList._longCount = targetCapacity;
|
||||||
targetList._lastBlockWithData = targetBlockIndex;
|
targetList._lastBlockWithData = targetBlockIndex;
|
||||||
targetList._version++;
|
targetList._version++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
|
internal static void AddRange<T>(this RecyclableLongList<T> targetList, RecyclableHashSet<T> items)
|
||||||
|
{
|
||||||
|
if (items._count == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
long sourceCount = items._count,
|
||||||
|
targetCapacity = targetList._longCount + sourceCount;
|
||||||
|
|
||||||
|
if (targetList._capacity < targetCapacity)
|
||||||
|
{
|
||||||
|
targetList._capacity = RecyclableLongList<T>.Helpers.Resize(targetList, targetList._blockSize, targetList._blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)targetCapacity)));
|
||||||
|
}
|
||||||
|
|
||||||
|
var blocks = targetList._memoryBlocks;
|
||||||
|
int blockIndex = targetList._nextItemBlockIndex,
|
||||||
|
itemIndex = targetList._nextItemIndex,
|
||||||
|
blockSize = targetList._blockSize;
|
||||||
|
|
||||||
|
var entries = items._entries;
|
||||||
|
int shift = items._blockShift,
|
||||||
|
mask = items._blockSizeMinus1;
|
||||||
|
|
||||||
|
for (long i = 0; i < sourceCount; i++)
|
||||||
|
{
|
||||||
|
blocks[blockIndex][itemIndex++] = entries[i >> shift][(int)(i & mask)].Value;
|
||||||
|
if (itemIndex == blockSize)
|
||||||
|
{
|
||||||
|
itemIndex = 0;
|
||||||
|
blockIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
targetList._longCount = targetCapacity;
|
||||||
|
targetList._nextItemBlockIndex = blockIndex;
|
||||||
|
targetList._nextItemIndex = itemIndex;
|
||||||
|
targetList._lastBlockWithData = blockIndex - (itemIndex > 0 ? 0 : 1);
|
||||||
|
targetList._version++;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
|
internal static void AddRange<T>(this RecyclableLongList<T> targetList, RecyclableStack<T> items)
|
||||||
|
{
|
||||||
|
if (items._count == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
long sourceCount = items._count,
|
||||||
|
targetCapacity = targetList._longCount + sourceCount;
|
||||||
|
|
||||||
|
if (targetList._capacity < targetCapacity)
|
||||||
|
{
|
||||||
|
targetList._capacity = RecyclableLongList<T>.Helpers.Resize(targetList, targetList._blockSize, targetList._blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)targetCapacity)));
|
||||||
|
}
|
||||||
|
|
||||||
|
var blocks = targetList._memoryBlocks;
|
||||||
|
int blockIndex = targetList._nextItemBlockIndex,
|
||||||
|
itemIndex = targetList._nextItemIndex,
|
||||||
|
blockSize = targetList._blockSize;
|
||||||
|
|
||||||
|
var chunk = items._current;
|
||||||
|
while (chunk != null)
|
||||||
|
{
|
||||||
|
var array = chunk.Value;
|
||||||
|
for (int i = chunk.Index - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
blocks[blockIndex][itemIndex++] = array[i];
|
||||||
|
if (itemIndex == blockSize)
|
||||||
|
{
|
||||||
|
itemIndex = 0;
|
||||||
|
blockIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
chunk = chunk.Previous;
|
||||||
|
}
|
||||||
|
|
||||||
|
targetList._longCount = targetCapacity;
|
||||||
|
targetList._nextItemBlockIndex = blockIndex;
|
||||||
|
targetList._nextItemIndex = itemIndex;
|
||||||
|
targetList._lastBlockWithData = blockIndex - (itemIndex > 0 ? 0 : 1);
|
||||||
|
targetList._version++;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
|
internal static void AddRange<T>(this RecyclableLongList<T> targetList, RecyclableSortedSet<T> items)
|
||||||
|
{
|
||||||
|
if (items._count == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
long sourceCount = items._count,
|
||||||
|
targetCapacity = targetList._longCount + sourceCount;
|
||||||
|
|
||||||
|
if (targetList._capacity < targetCapacity)
|
||||||
|
{
|
||||||
|
targetList._capacity = RecyclableLongList<T>.Helpers.Resize(targetList, targetList._blockSize, targetList._blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)targetCapacity)));
|
||||||
|
}
|
||||||
|
|
||||||
|
var blocks = targetList._memoryBlocks;
|
||||||
|
int blockIndex = targetList._nextItemBlockIndex,
|
||||||
|
itemIndex = targetList._nextItemIndex,
|
||||||
|
blockSize = targetList._blockSize;
|
||||||
|
|
||||||
|
int idx = 0;
|
||||||
|
while (idx < items._count)
|
||||||
|
{
|
||||||
|
blocks[blockIndex][itemIndex++] = items._items[idx++];
|
||||||
|
if (itemIndex == blockSize)
|
||||||
|
{
|
||||||
|
itemIndex = 0;
|
||||||
|
blockIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
targetList._longCount = targetCapacity;
|
||||||
|
targetList._nextItemBlockIndex = blockIndex;
|
||||||
|
targetList._nextItemIndex = itemIndex;
|
||||||
|
targetList._lastBlockWithData = blockIndex - (itemIndex > 0 ? 0 : 1);
|
||||||
|
targetList._version++;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
|
internal static void AddRange<T>(this RecyclableLongList<T> targetList, RecyclableLinkedList<T> items)
|
||||||
|
{
|
||||||
|
if (items._count == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
long sourceCount = items._count,
|
||||||
|
targetCapacity = targetList._longCount + sourceCount;
|
||||||
|
|
||||||
|
if (targetList._capacity < targetCapacity)
|
||||||
|
{
|
||||||
|
targetList._capacity = RecyclableLongList<T>.Helpers.Resize(targetList, targetList._blockSize, targetList._blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)targetCapacity)));
|
||||||
|
}
|
||||||
|
|
||||||
|
var blocks = targetList._memoryBlocks;
|
||||||
|
int blockIndex = targetList._nextItemBlockIndex,
|
||||||
|
itemIndex = targetList._nextItemIndex,
|
||||||
|
blockSize = targetList._blockSize;
|
||||||
|
|
||||||
|
var chunk = items._head;
|
||||||
|
while (chunk != null)
|
||||||
|
{
|
||||||
|
for (int i = chunk.Bottom; i < chunk.Top; i++)
|
||||||
|
{
|
||||||
|
blocks[blockIndex][itemIndex++] = chunk.Value[i];
|
||||||
|
if (itemIndex == blockSize)
|
||||||
|
{
|
||||||
|
itemIndex = 0;
|
||||||
|
blockIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
chunk = chunk.Next;
|
||||||
|
}
|
||||||
|
|
||||||
|
targetList._longCount = targetCapacity;
|
||||||
|
targetList._nextItemBlockIndex = blockIndex;
|
||||||
|
targetList._nextItemIndex = itemIndex;
|
||||||
|
targetList._lastBlockWithData = blockIndex - (itemIndex > 0 ? 0 : 1);
|
||||||
|
targetList._version++;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
|
internal static void AddRange<T>(this RecyclableLongList<T> targetList, RecyclablePriorityQueue<T> items)
|
||||||
|
{
|
||||||
|
if (items._size == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
long sourceCount = items._size,
|
||||||
|
targetCapacity = targetList._longCount + sourceCount;
|
||||||
|
|
||||||
|
if (targetList._capacity < targetCapacity)
|
||||||
|
{
|
||||||
|
targetList._capacity = RecyclableLongList<T>.Helpers.Resize(targetList, targetList._blockSize, targetList._blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)targetCapacity)));
|
||||||
|
}
|
||||||
|
|
||||||
|
var blocks = targetList._memoryBlocks;
|
||||||
|
int blockIndex = targetList._nextItemBlockIndex,
|
||||||
|
itemIndex = targetList._nextItemIndex,
|
||||||
|
blockSize = targetList._blockSize;
|
||||||
|
|
||||||
|
int idx = 0;
|
||||||
|
while (idx < items._size)
|
||||||
|
{
|
||||||
|
blocks[blockIndex][itemIndex++] = items._heap[idx++];
|
||||||
|
if (itemIndex == blockSize)
|
||||||
|
{
|
||||||
|
itemIndex = 0;
|
||||||
|
blockIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
targetList._longCount = targetCapacity;
|
||||||
|
targetList._nextItemBlockIndex = blockIndex;
|
||||||
|
targetList._nextItemIndex = itemIndex;
|
||||||
|
targetList._lastBlockWithData = blockIndex - (itemIndex > 0 ? 0 : 1);
|
||||||
|
targetList._version++;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
|
internal static void AddRange<T>(this RecyclableLongList<T> targetList, RecyclableQueue<T> items)
|
||||||
|
{
|
||||||
|
if (items._count == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
long sourceCount = items._count,
|
||||||
|
targetCapacity = targetList._longCount + sourceCount;
|
||||||
|
|
||||||
|
if (targetList._capacity < targetCapacity)
|
||||||
|
{
|
||||||
|
targetList._capacity = RecyclableLongList<T>.Helpers.Resize(targetList, targetList._blockSize, targetList._blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)targetCapacity)));
|
||||||
|
}
|
||||||
|
|
||||||
|
var blocks = targetList._memoryBlocks;
|
||||||
|
int blockIndex = targetList._nextItemBlockIndex,
|
||||||
|
itemIndex = targetList._nextItemIndex,
|
||||||
|
blockSize = targetList._blockSize;
|
||||||
|
|
||||||
|
var chunkQ = items._head;
|
||||||
|
while (chunkQ != null)
|
||||||
|
{
|
||||||
|
for (int i = chunkQ.Bottom; i < chunkQ.Top; i++)
|
||||||
|
{
|
||||||
|
blocks[blockIndex][itemIndex++] = chunkQ.Value[i];
|
||||||
|
if (itemIndex == blockSize)
|
||||||
|
{
|
||||||
|
itemIndex = 0;
|
||||||
|
blockIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
chunkQ = chunkQ.Next;
|
||||||
|
}
|
||||||
|
|
||||||
|
targetList._longCount = targetCapacity;
|
||||||
|
targetList._nextItemBlockIndex = blockIndex;
|
||||||
|
targetList._nextItemIndex = itemIndex;
|
||||||
|
targetList._lastBlockWithData = blockIndex - (itemIndex > 0 ? 0 : 1);
|
||||||
|
targetList._version++;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
|
internal static void AddRange<TKey, TValue>(this RecyclableLongList<KeyValuePair<TKey, TValue>> targetList, RecyclableDictionary<TKey, TValue> items)
|
||||||
|
{
|
||||||
|
if (items._count == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
long sourceCount = items._count,
|
||||||
|
targetCapacity = targetList._longCount + sourceCount;
|
||||||
|
|
||||||
|
if (targetList._capacity < targetCapacity)
|
||||||
|
{
|
||||||
|
targetList._capacity = RecyclableLongList<KeyValuePair<TKey, TValue>>.Helpers.Resize(targetList, targetList._blockSize, targetList._blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)targetCapacity)));
|
||||||
|
}
|
||||||
|
|
||||||
|
var blocks = targetList._memoryBlocks;
|
||||||
|
int blockIndex = targetList._nextItemBlockIndex,
|
||||||
|
itemIndex = targetList._nextItemIndex,
|
||||||
|
blockSize = targetList._blockSize;
|
||||||
|
|
||||||
|
var entries = items._entries;
|
||||||
|
int shift = items._blockShift,
|
||||||
|
mask = items._blockSizeMinus1;
|
||||||
|
|
||||||
|
for (long i = 0; i < sourceCount; i++)
|
||||||
|
{
|
||||||
|
ref var entry = ref entries[i >> shift][(int)(i & mask)];
|
||||||
|
blocks[blockIndex][itemIndex++] = new KeyValuePair<TKey, TValue>(entry.Key, entry.Value);
|
||||||
|
if (itemIndex == blockSize)
|
||||||
|
{
|
||||||
|
itemIndex = 0;
|
||||||
|
blockIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
targetList._longCount = targetCapacity;
|
||||||
|
targetList._nextItemBlockIndex = blockIndex;
|
||||||
|
targetList._nextItemIndex = itemIndex;
|
||||||
|
targetList._lastBlockWithData = blockIndex - (itemIndex > 0 ? 0 : 1);
|
||||||
|
targetList._version++;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
|
internal static void AddRange<TKey, TValue>(this RecyclableLongList<(TKey Key, TValue Value)> targetList, RecyclableSortedList<TKey, TValue> items)
|
||||||
|
{
|
||||||
|
if (items._count == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
long sourceCount = items._count,
|
||||||
|
targetCapacity = targetList._longCount + sourceCount;
|
||||||
|
|
||||||
|
if (targetList._capacity < targetCapacity)
|
||||||
|
{
|
||||||
|
targetList._capacity = RecyclableLongList<(TKey Key, TValue Value)>.Helpers.Resize(targetList, targetList._blockSize, targetList._blockSizePow2BitShift, checked((long)BitOperations.RoundUpToPowerOf2((ulong)targetCapacity)));
|
||||||
|
}
|
||||||
|
|
||||||
|
var blocks = targetList._memoryBlocks;
|
||||||
|
int blockIndex = targetList._nextItemBlockIndex,
|
||||||
|
itemIndex = targetList._nextItemIndex,
|
||||||
|
blockSize = targetList._blockSize;
|
||||||
|
|
||||||
|
int idx2 = 0;
|
||||||
|
while (idx2 < items._count)
|
||||||
|
{
|
||||||
|
blocks[blockIndex][itemIndex++] = (items._keys[idx2], items._values[idx2]);
|
||||||
|
idx2++;
|
||||||
|
if (itemIndex == blockSize)
|
||||||
|
{
|
||||||
|
itemIndex = 0;
|
||||||
|
blockIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
targetList._longCount = targetCapacity;
|
||||||
|
targetList._nextItemBlockIndex = blockIndex;
|
||||||
|
targetList._nextItemIndex = itemIndex;
|
||||||
|
targetList._lastBlockWithData = blockIndex - (itemIndex > 0 ? 0 : 1);
|
||||||
|
targetList._version++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7,15 +7,15 @@ namespace Recyclable.Collections
|
|||||||
{
|
{
|
||||||
internal sealed class RecyclablePriorityQueue<T> : IEnumerable<T>, IDisposable
|
internal sealed class RecyclablePriorityQueue<T> : IEnumerable<T>, IDisposable
|
||||||
{
|
{
|
||||||
private static readonly bool _needsClearing = !typeof(T).IsValueType;
|
internal static readonly bool _needsClearing = !typeof(T).IsValueType;
|
||||||
|
|
||||||
private readonly IComparer<T> _comparer;
|
internal readonly IComparer<T> _comparer;
|
||||||
|
|
||||||
#nullable disable
|
#nullable disable
|
||||||
private T[] _heap;
|
internal T[] _heap;
|
||||||
#nullable restore
|
#nullable restore
|
||||||
private int _size;
|
internal int _size;
|
||||||
private bool _disposed;
|
internal bool _disposed;
|
||||||
|
|
||||||
public RecyclablePriorityQueue(int initialCapacity = RecyclableDefaults.InitialCapacity, IComparer<T>? comparer = null)
|
public RecyclablePriorityQueue(int initialCapacity = RecyclableDefaults.InitialCapacity, IComparer<T>? comparer = null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ namespace Recyclable.Collections
|
|||||||
{
|
{
|
||||||
internal sealed class RecyclableQueue<T> : IEnumerable<T>, IDisposable
|
internal sealed class RecyclableQueue<T> : IEnumerable<T>, IDisposable
|
||||||
{
|
{
|
||||||
private static readonly bool _needsClearing = !typeof(T).IsValueType;
|
internal static readonly bool _needsClearing = !typeof(T).IsValueType;
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private static BiDirectionalRecyclableArrayPoolChunk<T> RentChunk(int size, BiDirectionalRecyclableArrayPoolChunk<T>? previous)
|
private static BiDirectionalRecyclableArrayPoolChunk<T> RentChunk(int size, BiDirectionalRecyclableArrayPoolChunk<T>? previous)
|
||||||
@@ -44,11 +44,11 @@ namespace Recyclable.Collections
|
|||||||
BiDirectionalRecyclableArrayPoolChunkPool<T>.Dispose(chunk, _needsClearing);
|
BiDirectionalRecyclableArrayPoolChunkPool<T>.Dispose(chunk, _needsClearing);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BiDirectionalRecyclableArrayPoolChunk<T> _head;
|
internal BiDirectionalRecyclableArrayPoolChunk<T> _head;
|
||||||
private BiDirectionalRecyclableArrayPoolChunk<T> _tail;
|
internal BiDirectionalRecyclableArrayPoolChunk<T> _tail;
|
||||||
private bool _disposed;
|
internal bool _disposed;
|
||||||
private long _capacity;
|
internal long _capacity;
|
||||||
private long _count;
|
internal long _count;
|
||||||
|
|
||||||
public RecyclableQueue(int initialCapacity = RecyclableDefaults.InitialCapacity)
|
public RecyclableQueue(int initialCapacity = RecyclableDefaults.InitialCapacity)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,13 +8,13 @@ namespace Recyclable.Collections
|
|||||||
internal sealed class RecyclableSortedList<TKey, TValue> : IEnumerable<(TKey Key, TValue Value)>, IDisposable
|
internal sealed class RecyclableSortedList<TKey, TValue> : IEnumerable<(TKey Key, TValue Value)>, IDisposable
|
||||||
where TKey : notnull
|
where TKey : notnull
|
||||||
{
|
{
|
||||||
private static readonly bool _needsClearing = !typeof(TKey).IsValueType || !typeof(TValue).IsValueType;
|
internal static readonly bool _needsClearing = !typeof(TKey).IsValueType || !typeof(TValue).IsValueType;
|
||||||
|
|
||||||
private TKey[] _keys;
|
internal TKey[] _keys;
|
||||||
private TValue[] _values;
|
internal TValue[] _values;
|
||||||
private int _count;
|
internal int _count;
|
||||||
private readonly IComparer<TKey> _comparer;
|
internal readonly IComparer<TKey> _comparer;
|
||||||
private bool _disposed;
|
internal bool _disposed;
|
||||||
|
|
||||||
public RecyclableSortedList(int initialCapacity = RecyclableDefaults.InitialCapacity, IComparer<TKey>? comparer = null)
|
public RecyclableSortedList(int initialCapacity = RecyclableDefaults.InitialCapacity, IComparer<TKey>? comparer = null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,13 +7,13 @@ namespace Recyclable.Collections
|
|||||||
{
|
{
|
||||||
internal sealed class RecyclableSortedSet<T> : IEnumerable<T>, IDisposable where T : notnull
|
internal sealed class RecyclableSortedSet<T> : IEnumerable<T>, IDisposable where T : notnull
|
||||||
{
|
{
|
||||||
private static readonly bool _needsClearing = !typeof(T).IsValueType;
|
internal static readonly bool _needsClearing = !typeof(T).IsValueType;
|
||||||
|
|
||||||
private readonly IComparer<T> _comparer;
|
internal readonly IComparer<T> _comparer;
|
||||||
|
|
||||||
private T[] _items;
|
internal T[] _items;
|
||||||
private int _count;
|
internal int _count;
|
||||||
private bool _disposed;
|
internal bool _disposed;
|
||||||
|
|
||||||
public RecyclableSortedSet(int initialCapacity = RecyclableDefaults.InitialCapacity, IComparer<T>? comparer = null)
|
public RecyclableSortedSet(int initialCapacity = RecyclableDefaults.InitialCapacity, IComparer<T>? comparer = null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ namespace Recyclable.Collections
|
|||||||
{
|
{
|
||||||
internal sealed class RecyclableStack<T> : IEnumerable<T>, IDisposable
|
internal sealed class RecyclableStack<T> : IEnumerable<T>, IDisposable
|
||||||
{
|
{
|
||||||
private static readonly bool _needsClearing = !typeof(T).IsValueType;
|
internal static readonly bool _needsClearing = !typeof(T).IsValueType;
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private static RecyclableArrayPoolChunk<T> RentChunk(int size, RecyclableArrayPoolChunk<T>? previous)
|
private static RecyclableArrayPoolChunk<T> RentChunk(int size, RecyclableArrayPoolChunk<T>? previous)
|
||||||
@@ -42,10 +42,10 @@ namespace Recyclable.Collections
|
|||||||
RecyclableArrayPoolChunkPool<T>.Dispose(chunk, _needsClearing);
|
RecyclableArrayPoolChunkPool<T>.Dispose(chunk, _needsClearing);
|
||||||
}
|
}
|
||||||
|
|
||||||
private RecyclableArrayPoolChunk<T> _current;
|
internal RecyclableArrayPoolChunk<T> _current;
|
||||||
private bool _disposed;
|
internal bool _disposed;
|
||||||
private long _capacity;
|
internal long _capacity;
|
||||||
private long _count;
|
internal long _count;
|
||||||
|
|
||||||
public RecyclableStack(int initialCapacity = RecyclableDefaults.InitialCapacity)
|
public RecyclableStack(int initialCapacity = RecyclableDefaults.InitialCapacity)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in new issue
Block a user