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