using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
#pragma warning disable 0420
public partial class LockFreeDictionary<K, V> : IDictionary<K, V>
where K : IEquatable<K>
where V : IEquatable<V>
{
public partial class Config
{
/// <summary>
/// Lock-free LIFO stack
/// </summary>
public partial struct Freelist
{
public Freelist(Config cfg)
{
this.cfg = cfg;
this.m_head = unchecked((UInt32)FreeListTerminator);
}
internal const Int32 FreeListTerminator = unchecked((Int32)0xFFFFFFFE);
const Int64 SequenceMask = unchecked((Int64)0xFFFFFFFF00000000);
const Int64 SequenceIncrement = 0x0000000100000000;
readonly Config cfg;
Int64 m_head;
/// <summary>
/// Add an item to the free list
/// </summary>
public void AddIndexToFreeList(int gx_add)
{
Int64 new_head, head = AtomicRead64(ref m_head);
while (true)
{
cfg.SetEntryNext(gx_add, (Int32)head);
new_head = ((head + SequenceIncrement) & SequenceMask) | (UInt32)gx_add;
if ((new_head = Interlocked.CompareExchange(ref m_head, new_head, head)) == head)
return;
head = new_head;
}
}
/// <summary>
/// Pick the first item from the free list.
/// </summary>
/// <returns><value>true</value> if an free slot is returned in <paramref name="gx_out"/>,
/// <value>false</value> otherwise.</returns>
public bool TryGetFreeIndex(out int gx_out)
{
Int64 new_head, head = AtomicRead64(ref m_head);
while (true)
{
int gx_next;
while (true)
{
gx_out = (Int32)head;
gx_next = cfg.GetEntryNext(gx_out);
Int64 same_head = AtomicRead64(ref m_head);
if (head == same_head)
break;
head = same_head;
}
if (gx_out == FreeListTerminator)
{
gx_out = -1;
return false;
}
new_head = ((head + SequenceIncrement) & SequenceMask) | (UInt32)gx_next;
if ((new_head = Interlocked.CompareExchange(ref m_head, new_head, head)) == head)
return true;
head = new_head;
}
}
};
};
};