using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using glue;
using glue.Debugging;

#pragma warning disable 0649

namespace agree
{
	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	/// <summary>
	/// 
	/// </summary>
	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	sealed public class SpinLockTray : Tray
	{
		public SpinLockTray(int tix, TypeMgr tm, int next_mark, int next_id)
			: base(tix, tm, next_mark, next_id)
		{
			for (int i = 0; i < Pools.Length; i++)
				Pools[i] = new SpinLockTrayConstraintPool(this, i);
		}

		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>
		/// 
		/// </summary>
		///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		public sealed class SpinLockTrayConstraintPool : ConstraintPool
		{
			public SpinLockTrayConstraintPool(Tray tr, int i_feat)
				: base(tr, i_feat)
			{
				Nop.X(fsp1, fsp2);
			}

			FalseSharing.Padding60 fsp1;
			SpinLock m_lock = new SpinLock(false);	// do not make this 'readonly'
			FalseSharing.Padding60 fsp2;

			Dictionary<Int32, Edge> dict = new Dictionary<Int32, Edge>();

			///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 
			/// </summary>
			///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			public override Edge GetEdge(Int32 m)
			{
				Debug.Assert(m != 0);
				bool entered = false;
				try
				{
					m_lock.Enter(ref entered);
					Edge c;
					dict.TryGetValue(m, out c);
					return c;
				}
				finally
				{
					if (entered)
						m_lock.Exit(false);
				}
			}

			///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 
			/// </summary>
			///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			public override bool TryGetEdge(Int32 m, out Edge e)
			{
				Debug.Assert(m != 0);
				bool entered = false;
				try
				{
					m_lock.Enter(ref entered);
					return dict.TryGetValue(m, out e);
				}
				finally
				{
					if (entered)
						m_lock.Exit(false);
				}
			}

			///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// Store the constraint for the specified mark. Handle Edge value semantics properly.
			/// Allows detached mark to be set for bare or atomic types
			/// </summary>
			///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			public override void SetEdge(Int32 m, Edge c)
			{
				Debug.Assert(m != 0 && m >= tr._protect_mark && c.FlagsId != 0);
				bool entered = false;
				try
				{
					m_lock.Enter(ref entered);
					dict[m] = c;
				}
				finally
				{
					if (entered)
						m_lock.Exit(false);
				}
			}

			///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 
			/// </summary>
			///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			public override void RemoveEdge(Int32 m)
			{
				Debug.Assert(m != 0 && m >= tr._protect_mark);
				bool entered = false;
				try
				{
					m_lock.Enter(ref entered);
					dict.Remove(m);
				}
				finally
				{
					if (entered)
						m_lock.Exit(false);
				}
			}


			///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 
			/// </summary>
			///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			public override bool TryRemoveEdge(Int32 m, out Edge e)
			{
				Debug.Assert(m != 0 && m >= tr._protect_mark);
				bool entered = false;
				try
				{
					m_lock.Enter(ref entered);
					return dict.TryGetValue(m, out e) ? dict.Remove(m) : false;
				}
				finally
				{
					if (entered)
						m_lock.Exit(false);
				}
			}

			///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 
			/// </summary>
			///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			public override bool ContainsInMark(Int32 m)
			{
				Debug.Assert(m != 0);
				bool entered = false;
				try
				{
					m_lock.Enter(ref entered);
					return dict.ContainsKey(m);
				}
				finally
				{
					if (entered)
						m_lock.Exit(false);
				}
			}

			///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 
			/// </summary>
			///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			public override int Count
			{
				get
				{
					bool entered = false;
					try
					{
						m_lock.Enter(ref entered);
						return dict.Count;
					}
					finally
					{
						if (entered)
							m_lock.Exit(false);
					}
				}
			}

			///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// not locked
			/// </summary>
			///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			public override IEnumerable<int> Marks
			{
				get
				{
					tr.mre_truncate_ok.WaitOne();
					return dict.Keys;
				}
			}

			///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 
			/// </summary>
			///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			public override IEnumerable<Edge> Edges
			{
				get
				{
					tr.mre_truncate_ok.WaitOne();
					return dict.Values;
				}
			}

			///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			/// <summary>
			/// 
			/// </summary>
			///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			public override IEnumerable<KeyValuePair<int, Edge>> PoolEdges
			{
				get
				{
					tr.mre_truncate_ok.WaitOne();
					return dict;
				}
			}
		};
	};
}