/// <summary>
        /// Remove an item from one of the queues. Specifically, it removes the
        /// oldest item from the next queue in order to provide fair access to
        /// all of the queues
        /// </summary>
        public bool TryDequeue(out EntityUpdate value)
        {
            // If there is anything in immediate queues, return it first no
            // matter what else. Breaks fairness. But very useful.

            for (int iq = 0; iq < NumberOfImmediateQueues; iq++)
            {
                if (m_heaps[iq].Count > 0)
                {
                    value = m_heaps[iq].RemoveNext();
                    return(m_lookupTable.TryRemove(value.Entity.LocalId, out value));
                }
            }

            // To get the fair queing, we cycle through each of the
            // queues when finding an element to dequeue.
            // We pull (NumberOfQueues - QueueIndex) items from each queue in order
            // to give lower numbered queues a higher priority and higher percentage
            // of the bandwidth.

            PriorityMinHeap curheap = m_heaps[m_nextQueue];

            // Check for more items to be pulled from the current queue
            if (m_countFromQueue > 0 && curheap.Count > 0)
            {
                --m_countFromQueue;

                value = curheap.RemoveNext();
                return(m_lookupTable.TryRemove(value.Entity.LocalId, out value));
            }

            // Find the next non-immediate queue with updates in it
            for (int i = NumberOfImmediateQueues; i < NumberOfQueues; ++i)
            {
                m_nextQueue++;
                if (m_nextQueue >= NumberOfQueues)
                {
                    m_nextQueue = NumberOfImmediateQueues;
                }

                curheap = m_heaps[m_nextQueue];
                if (curheap.Count == 0)
                {
                    continue;
                }

                m_countFromQueue = m_queueCounts[m_nextQueue];
                --m_countFromQueue;

                value = curheap.RemoveNext();
                return(m_lookupTable.TryRemove(value.Entity.LocalId, out value));
            }

            value = null;
            return(false);
        }
        public PriorityQueue(int capacity)
        {
            capacity /= 4;
            for (int i = 0; i < m_heaps.Length; ++i)
            {
                m_heaps[i] = new PriorityMinHeap(capacity);
            }

            m_lookupTable    = new ConcurrentDictionary <uint, EntityUpdate>();
            m_nextQueue      = NumberOfImmediateQueues;
            m_countFromQueue = m_queueCounts[m_nextQueue];
        }
        public bool TryOrderedDequeue(out EntityUpdate value)
        {
            for (int iq = 0; iq < NumberOfQueues; ++iq)
            {
                PriorityMinHeap curheap = m_heaps[iq];
                if (curheap.Count > 0)
                {
                    value = curheap.RemoveNext();
                    return(m_lookupTable.TryRemove(value.Entity.LocalId, out value));
                }
            }

            value = null;
            return(false);
        }