using System; using System.Collections.Generic; using System.Runtime.InteropServices; 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> /// /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public partial class EntryBlock { public EntryBlock(Config cfg, int block_no) { this.cfg = cfg; this.i_block = block_no; this.rg = new Entry[cfg.EntriesPerBlock]; } readonly Config cfg; readonly Entry[] rg; internal EntryBlock next = null; internal void StoreEntryHot(int offs, ref Entry e) { Thread.MemoryBarrier(); rg[offs] = e; } internal void SetEntryNext(int offs, int gx_next) { rg[offs].gx_next = gx_next; /// C# volatile } internal void SetFreelistNext(int offs, int gx_next) { rg[offs].gx_next = gx_next; /// C# volatile rg[offs].hash = Entry.FreelistHash; } internal void SetEntryHash(int offs, uint h) { rg[offs].hash = h; /// C# volatile } internal int TransactEntryNext(int offs, int gx_next, int gx_compare) { return Interlocked.CompareExchange(ref rg[offs].gx_next, gx_next, gx_compare); } internal int GetNextHot(int offs) { return rg[offs].gx_next; /// C# volatile } internal uint GetHashAndNextHot(int offs, out int gx_next) { gx_next = rg[offs].gx_next; /// C# volatile return rg[offs].hash; /// C# volatile } internal void GetEntryHot(int offs, out Entry e) { e = rg[offs]; Thread.MemoryBarrier(); } internal void GetKeyHot(int offs, out K key) { key = rg[offs].key; Thread.MemoryBarrier(); } internal void GetValueHot(int offs, out V value) { value = rg[offs].value; Thread.MemoryBarrier(); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// /// </summary> /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public partial struct Entry { #if DEBUG static internal Entry AllocDefault = new Entry(-1, 0, default(K), default(V)); static internal Entry FreelistDefault = new Entry(0, 0, default(K), default(V)); #endif internal const int FreelistHash = 0; /// to merit 'beforefieldinit' semantics, we eschew doing all of the following in a static constructor static readonly Type t_key = typeof(K); static readonly Type t_value = typeof(V); static internal readonly bool f_value_type_key = t_key.IsValueType; static internal readonly bool f_value_type_value = t_value.IsValueType; static internal readonly bool f_key_null_check = !f_value_type_key || Nullable.GetUnderlyingType(t_key) != null; static internal int StructureSize { get { return cb_ent; } } static readonly int cb_ent = sizeof(int) + sizeof(uint) + (f_value_type_key ? Marshal.SizeOf(default(K)) : IntPtr.Size) + (f_value_type_value ? Marshal.SizeOf(default(V)) : IntPtr.Size); internal Entry(int gx_next, uint hash, K key, V value) { this.gx_next = gx_next; this.hash = hash; this.key = key; this.value = value; } internal Entry(uint hash, K key, V value) : this(-1, hash, key, value) { } volatile internal int gx_next; volatile internal uint hash; readonly internal K key; readonly internal V value; static internal bool CompareValues(V v1, V v2) { return (!f_value_type_value && v1 == null) ? v2 == null : v1.Equals(v2); } }; }; }; };