IndexPool
public struct IndexPool : ISupplier<int>, IFunctional<Func<int>>, IConsumer<int>, IFunctional<Action<int>>, IReadOnlyCollection<int>, IEnumerable<int>, IEnumerable, IResettable
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();
}
}
}