DotNext.Threading by .NET Foundation and Contributors

<PackageReference Include="DotNext.Threading" Version="5.7.0" />

 IndexPool

Represents a pool of integer values.
using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Threading; namespace DotNext.Collections.Concurrent { [StructLayout(LayoutKind.Auto)] [EditorBrowsable(EditorBrowsableState.Advanced)] public struct IndexPool : IReadOnlyCollection<int>, IEnumerable<int>, IEnumerable { [StructLayout(LayoutKind.Auto)] public struct Enumerator { private readonly ulong bitmask; private readonly int maxValue; private int current; public int Current { [IsReadOnly] get { return current; } } internal Enumerator(ulong bitmask, int maxValue) { this.bitmask = bitmask; this.maxValue = maxValue; current = -1; } public bool MoveNext() { while (++current <= maxValue) { if (Contains(bitmask, current)) return true; } return false; } internal IEnumerator<int> AsClassicEnumerator() { while (MoveNext()) { yield return Current; } } } private readonly int maxValue; private ulong bitmask; public bool IsEmpty { [IsReadOnly] get { return Count == 0; } set { bitmask = (ulong)(value ? 0 : (-1)); } } public static int MaxValue => Capacity - 1; public static int Capacity => 64; public int Count { [IsReadOnly] get { return Math.Min(BitOperations.PopCount(bitmask), maxValue + 1); } } public IndexPool() { bitmask = ulong.MaxValue; maxValue = MaxValue; } public IndexPool(int maxValue) { if ((uint)maxValue > (uint)MaxValue) throw new ArgumentOutOfRangeException("maxValue"); bitmask = ulong.MaxValue; this.maxValue = maxValue; } [IsReadOnly] public bool TryPeek(out int result) { return (result = BitOperations.TrailingZeroCount(Volatile.Read(ref bitmask))) <= maxValue; } public bool TryTake(out int result) { return <TryTake>g__TryTake|12_0(ref bitmask, maxValue, out result); } public int Take() { if (!TryTake(out int result)) <Take>g__ThrowOverflowException|13_0(); return result; } public int Take(Span<int> indices) { if (indices.Length < Capacity) throw new ArgumentOutOfRangeException("indices"); ulong num = Interlocked.Exchange(ref bitmask, 0); int num2 = 0; for (int i = 0; i < Capacity; i++) { if (Contains(num, i)) indices[num2++] = i; } return num2; } int Invoke() { return Take(); } public void Return(int value) { if ((uint)value > (uint)maxValue) <Return>g__ThrowArgumentOutOfRangeException|16_0(); Interlocked.Or(ref bitmask, (ulong)(1 << value)); } public void Return(ReadOnlySpan<int> indices) { ulong num = 0; ReadOnlySpan<int> readOnlySpan = indices; foreach (int num2 in readOnlySpan) { num = (ulong)((long)num | (1 << num2)); } Interlocked.Or(ref bitmask, num); } public void Reset() { Volatile.Write(ref bitmask, ulong.MaxValue); } void Invoke(int value) { Return(value); } [IsReadOnly] public bool Contains(int value) { if ((uint)value <= (uint)maxValue) return Contains(Volatile.Read(ref bitmask), value); return false; } private static bool Contains(ulong bitmask, int index) { return ((long)bitmask & (1 << index)) != 0; } [IsReadOnly] public Enumerator GetEnumerator() { return new Enumerator(Volatile.Read(ref bitmask), maxValue); } [IsReadOnly] IEnumerator<int> IEnumerable<int>.GetEnumerator() { return GetEnumerator().AsClassicEnumerator(); } [IsReadOnly] IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator().AsClassicEnumerator(); } } }