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; } } }; }; };