
namespace Fivestops.Oxide
{
    class OxideThreadPool
    {
        private static OxideThreadPool s_otpPool = null;

        private Queue m_qRequestQueue;

        private long m_lThreadsInUse = 0;
        private long m_lCurrentThreads = 0;
        

        static OxideThreadPool()
        {
            s_otpPool = new OxideThreadPool();
        }

        private OxideThreadPool()
        {
            m_qRequestQueue = Queue.Synchronized (new Queue());
        }

        private void QueueUserWorkItem (WaitCallback callback, object context)
        {
            OxideThreadPoolItem otpiItem = new OxideThreadPoolItem();

            otpiItem.Callback = callback;
            otpiItem.Context = context;

            m_qRequestQueue.Enqueue (otpiItem);
        }
        
        public static void QueueUserWorkItem (WaitCallback callback)
        {
            s_otpPool.QueueUserWorkItem (callback, null);
        }

        public static void QueueUserWorkItem (WaitCallback callback, object context)
        {
            s_otpPool.QueueUserWorkItem (callback, context);
        }

        private void WorkerThread()
        {
            bool bWaitFor = false;

            try
            {
                Interlocked.Increment (ref m_lCurrentThreads);

                while (true)
                {
                    try
                    {
                        OxideThreadPoolItem otpiItem = (OxideThreadPoolItem) m_qRequestQueue.Dequeue();

                        try
                        {
                            Interlocked.Increment (ref m_lThreadsInUse);

                            otpiItem.Callback (otpiItem.Context);
                        }
                        finally
                        {
                            Interlocked.Decrement (ref m_lThreadsInUse);
                        }
                    }
                    catch (InvalidOperationException)
                    {
                        bWait = true;
                    }
                }
            }
            finally
            {
                Interlocked.Decrement (ref m_lCurrentThreads);
            }
        }

        struct OxideThreadPoolItem
        {
            public WaitCallback Callback;
            public object Context;
        }
    }
}
