Esempio n. 1
0
        /// <summary>
        /// Constructs a new PriorityQueue instance.
        /// </summary>
        public PriorityQueue()
        {
            peekWaitHeader          = new WaitingThreadNode();
            peekWaitHeader.next     = peekWaitHeader;
            peekWaitHeader.previous = peekWaitHeader;

            removeWaitHeader          = new WaitingThreadNode();
            removeWaitHeader.next     = removeWaitHeader;
            removeWaitHeader.previous = removeWaitHeader;

            waitNodeCacheHeader = new WaitingThreadNode();

            Sublist sublist;

            for (int x = 0; x <= 20; x++)
            {
                sublist          = new Sublist();
                sublist.priority = x;
                sublistArray[x]  = sublist;
                sublistMap.Add(x, sublist);
            }
            sublistCount           = 21;
            highestPrioritySublist = null;
            defaultPrioritySublist = sublistArray[0];
        }
Esempio n. 2
0
        /// <summary>
        /// Constructs a new DoubleEndedQueue instance
        /// </summary>
        public DoubleEndedQueue()
        {
            peekWaitHeader          = new WaitingThreadNode();
            peekWaitHeader.next     = peekWaitHeader;
            peekWaitHeader.previous = peekWaitHeader;

            removeWaitHeader          = new WaitingThreadNode();
            removeWaitHeader.next     = removeWaitHeader;
            removeWaitHeader.previous = removeWaitHeader;

            waitNodeCacheHeader = new WaitingThreadNode();
        }
Esempio n. 3
0
        /// <summary>
        /// Constructs a new DoubleEndedQueue instance
        /// </summary>
        public DoubleEndedQueue()
        {
            peekWaitHeader = new WaitingThreadNode();
            peekWaitHeader.next = peekWaitHeader;
            peekWaitHeader.previous = peekWaitHeader;

            removeWaitHeader = new WaitingThreadNode();
            removeWaitHeader.next = removeWaitHeader;
            removeWaitHeader.previous = removeWaitHeader;

            waitNodeCacheHeader = new WaitingThreadNode();
        }
Esempio n. 4
0
        /// <summary>
        /// Constructs a new PriorityQueue instance.
        /// </summary>
        public PriorityQueue()
        {
            peekWaitHeader = new WaitingThreadNode();
            peekWaitHeader.next = peekWaitHeader;
            peekWaitHeader.previous = peekWaitHeader;

            removeWaitHeader = new WaitingThreadNode();
            removeWaitHeader.next = removeWaitHeader;
            removeWaitHeader.previous = removeWaitHeader;

            waitNodeCacheHeader = new WaitingThreadNode();

            Sublist sublist;
            for (int x = 0; x <= 20; x++)
            {
                sublist = new Sublist();
                sublist.priority = x;
                sublistArray[x] = sublist;
                sublistMap.Add(x, sublist);
            }
            sublistCount = 21;
            highestPrioritySublist = null;
            defaultPrioritySublist = sublistArray[0];
        }
Esempio n. 5
0
        /// <summary>
        /// Renders this Queue incapable of accepting further input, and immediately
        /// returns null to any waiting threads
        /// </summary>
        public override void Close()
        {
            lock (monitor)
            {
                if (!isOpen)
                {
                    return;
                }
                WaitingThreadNode node;

                if (peekWaitCount > 0)
                {
                    lock (peekWaitHeader)
                    {
                        if (peekWaitCount > 0)
                        {
                            node = peekWaitHeader.next;
                            while (node != peekWaitHeader)
                            {
                                node.valueReturned = true;
                                node.returnValue   = null;
                                node.previous      = null;
                                node = node.next;
                                node.previous.next = null;
                            }
                            peekWaitCount       = 0;
                            peekWaitHeader.next = null;
                            Monitor.PulseAll(peekWaitHeader);
                        }
                    }
                }

                if (removeWaitCount > 0)
                {
                    lock (removeWaitHeader)
                    {
                        if (removeWaitCount > 0)
                        {
                            node = removeWaitHeader.next;
                            WaitingThreadNode[] nodes = new WaitingThreadNode[removeWaitCount];
                            for (int x = 0; x < removeWaitCount; x++)
                            {
                                nodes[x]           = node;
                                node.valueReturned = true;
                                node.returnValue   = null;
                                node.previous      = null;
                                node = node.next;
                                node.previous.next = null;
                            }
                            for (int x = 0; x < removeWaitCount; x++)
                            {
                                lock (nodes[x])
                                {
                                    Monitor.Pulse(nodes[x]);
                                }
                            }
                            removeWaitHeader.next     = removeWaitHeader;
                            removeWaitHeader.previous = removeWaitHeader;
                            removeWaitCount           = 0;
                        }
                    }
                }
            }
        }
Esempio n. 6
0
        /// <summary>
        /// Removes the next (highest-priority) object from the queue, or null if
        /// the queue is initially empty and the specified timeout is reached without
        /// input
        /// </summary>
        /// <param name="_millisecondsTimeout"></param>
        /// <returns>The next object from the highest priority currently contained by the queue</returns>
        public override object Remove(int _millisecondsTimeout)
        {
            object returnValue = null;

            lock (monitor)
            {
                if (count > 0)
                {
                    if (highestPrioritySublist != null)
                    {
                        returnValue = highestPrioritySublist.RemoveFirst();
                        if (highestPrioritySublist.count == 0)
                        {
                            highestPrioritySublist = null;
                        }
                        count--;
                        return(returnValue);
                    }
                    else
                    {
                        Sublist sublist;
                        for (int x = (sublistCount - 1); x >= 0; x--)
                        {
                            sublist = sublistArray[x];
                            if (sublist.count > 0)
                            {
                                returnValue = sublist.RemoveFirst();
                                if (sublist.count > 0)
                                {
                                    highestPrioritySublist = sublist;
                                }
                                count--;
                                return(returnValue);
                            }
                        }
                    }
                }

                if ((_millisecondsTimeout <= 0) || (!isOpen))
                {
                    return(null);
                }
            }

            WaitingThreadNode node;

            lock (removeWaitHeader)
            {
                peekWaitCount++;


                if (waitNodeCacheCount > 0)
                {
                    node = waitNodeCacheHeader.next;
                    waitNodeCacheHeader.next = node.next;
                    waitNodeCacheCount--;
                }
                else
                {
                    node = new WaitingThreadNode();
                }

                removeWaitHeader.previous.next = node;
                node.previous             = removeWaitHeader.previous;
                removeWaitHeader.previous = node;
                node.next = removeWaitHeader;
            }

            lock (node)
            {
                if (!node.valueReturned)
                {
                    try
                    {
                        Monitor.Wait(node, _millisecondsTimeout);
                    }
                    catch { }
                }
            }

            lock (removeWaitHeader)
            {
                if (node.valueReturned)
                {
                    returnValue        = node.returnValue;
                    node.returnValue   = null;
                    node.valueReturned = false;
                }
                else
                {
                    node.previous.next = node.next;
                    node.next.previous = node.previous;
                    node.previous      = null;
                    peekWaitCount--;
                }

                node.next = waitNodeCacheHeader.next;
                waitNodeCacheHeader.next = node;
                waitNodeCacheCount++;
            }

            return(returnValue);
        }
Esempio n. 7
0
        /// <summary>
        /// Gets the next (highest-priority) object without removing it from the queue
        /// </summary>
        /// <param name="_millisecondsTimeout">The number of milliseconds to wait for input if the queue is initially empty</param>
        /// <returns>The highest-priority object on the queue, or null if the queue is initially empty and the timeout expires</returns>
        public override object Peek(int _millisecondsTimeout)
        {
            lock (monitor)
            {
                if (count > 0)
                {
                    if (highestPrioritySublist != null)
                    {
                        return(highestPrioritySublist.elements[highestPrioritySublist.startIndex]);
                    }
                    else
                    {
                        for (int x = (sublistCount - 1); x > 0; x--)
                        {
                            if (sublistArray[x].count > 0)
                            {
                                highestPrioritySublist = sublistArray[x];
                                return(highestPrioritySublist.elements[highestPrioritySublist.startIndex]);
                            }
                        }
                    }
                }

                if ((_millisecondsTimeout <= 0) || (!isOpen))
                {
                    return(null);
                }
            }

            object returnValue = null;

            lock (peekWaitHeader)
            {
                peekWaitCount++;

                WaitingThreadNode node;

                if (waitNodeCacheCount > 0)
                {
                    node = waitNodeCacheHeader.next;
                    waitNodeCacheHeader.next = node.next;
                    waitNodeCacheCount--;
                }
                else
                {
                    node = new WaitingThreadNode();
                }

                peekWaitHeader.previous.next = node;
                node.previous           = peekWaitHeader.previous;
                peekWaitHeader.previous = node;
                node.next = peekWaitHeader;

                try
                {
                    Monitor.Wait(peekWaitHeader, _millisecondsTimeout);
                }
                catch { }

                if (node.valueReturned)
                {
                    returnValue        = node.returnValue;
                    node.returnValue   = null;
                    node.valueReturned = false;
                }
                else
                {
                    node.previous.next = node.next;
                    node.next.previous = node.previous;
                    node.previous      = null;
                    peekWaitCount--;
                }

                node.next = waitNodeCacheHeader.next;
                waitNodeCacheHeader.next = node;
                waitNodeCacheCount++;
            }
            return(returnValue);
        }
Esempio n. 8
0
        /// <summary>
        /// Adds the specified object to the queue with the default priority
        /// (see the DefaultPriority property)
        /// </summary>
        /// <param name="_object">The object to add to the queue</param>
        public override void Add(object _object)
        {
            lock (monitor)
            {
                if (!isOpen)
                {
                    throw new InvalidOperationException("This instance is closed, and cannot accept input");
                }
                else if ((!isNullAllowed) && (_object == null))
                {
                    throw new ArgumentNullException("This instance does not allow null input");
                }

                if (peekWaitCount > 0)
                {
                    lock (peekWaitHeader)
                    {
                        if (peekWaitCount > 0)
                        {
                            WaitingThreadNode node;
                            node = peekWaitHeader.next;
                            while (node != peekWaitHeader)
                            {
                                node.valueReturned = true;
                                node.returnValue   = _object;
                                node.previous      = null;
                                node = node.next;
                                node.previous.next = null;
                            }
                            peekWaitCount       = 0;
                            peekWaitHeader.next = null;
                            Monitor.PulseAll(peekWaitHeader);
                        }
                    }
                }

                if (removeWaitCount > 0)
                {
                    lock (removeWaitHeader)
                    {
                        if (removeWaitCount > 0)
                        {
                            WaitingThreadNode node = removeWaitHeader.next;
                            removeWaitHeader.next          = node.next;
                            removeWaitHeader.next.previous = removeWaitHeader;
                            node.next     = null;
                            node.previous = null;
                            removeWaitCount--;

                            lock (node)
                            {
                                node.valueReturned = true;
                                node.returnValue   = _object;
                                Monitor.Pulse(node);
                            }
                        }
                    }
                }
                else
                {
                    defaultPrioritySublist.AddLast(_object);
                    if ((highestPrioritySublist == null) || (highestPrioritySublist.priority < defaultPriority))
                    {
                        highestPrioritySublist = defaultPrioritySublist;
                    }
                    count++;
                }
            }
        }
Esempio n. 9
0
        /// <summary>
        /// Removes and returns the object at the back of the queue.  If the queue
        /// is currently empty, waits the specified number of milliseconds for the next
        /// input to the queue
        /// </summary>
        /// <param name="_millisecondsTimeout">The number of milliseconds to wait</param>
        /// <returns>The object at the back of the queue, or null if the queue was initially empty and the timeout expired</returns>
        public object RemoveLast(int _millisecondsTimeout)
        {
            object returnValue = null;
            lock (syncObj)
            {
                if (count > 0)
                {
                    returnValue = elements[endIndex--];
                    if (endIndex < 0)
                    {
                        endIndex = capacity - 1;
                    }
                    count--;
                    return returnValue;
                }

                if ((_millisecondsTimeout <= 0) || (!isOpen))
                {
                    return null;
                }
            }

            WaitingThreadNode node;

            lock (removeWaitHeader)
            {
                peekWaitCount++;

                if (waitNodeCacheCount > 0)
                {
                    node = waitNodeCacheHeader.next;
                    waitNodeCacheHeader.next = node.next;
                    waitNodeCacheCount--;
                }
                else
                {
                    node = new WaitingThreadNode();
                }

                removeWaitHeader.previous.next = node;
                node.previous = removeWaitHeader.previous;
                removeWaitHeader.previous = node;
                node.next = removeWaitHeader;

            }

            lock (node)
            {
                if (!node.valueReturned)
                {
                    try
                    {
                        Monitor.Wait(node, _millisecondsTimeout);
                    }
                    catch { }
                }
            }

            lock (removeWaitHeader)
            {
                if (node.valueReturned)
                {
                    returnValue = node.returnValue;
                    node.returnValue = null;
                    node.valueReturned = false;
                }
                else
                {
                    node.previous.next = node.next;
                    node.next.previous = node.previous;
                    node.previous = null;
                    peekWaitCount--;
                }

                node.next = waitNodeCacheHeader.next;
                waitNodeCacheHeader.next = node;
                waitNodeCacheCount++;

            }

            return returnValue;
        }
Esempio n. 10
0
        /// <summary>
        /// Gets the object at the back of the queue without removing it.  If the queue
        /// is currently empty, waits the specified number of milliseconds for the next
        /// input to the queue
        /// </summary>
        /// <param name="_millisecondsTimeout">The number of milliseconds to wait</param>
        /// <returns>The object at the back of the queue, or null if the queue was initially empty and the timeout expired</returns>
        public object PeekLast(int _millisecondsTimeout)
        {
            lock (syncObj)
            {
                if (count > 0)
                {
                    return elements[endIndex];
                }
                if ((_millisecondsTimeout <= 0) || (!isOpen))
                {
                    return null;
                }
            }

            object returnValue = null;
            lock (peekWaitHeader)
            {
                peekWaitCount++;

                WaitingThreadNode node;

                if (waitNodeCacheCount > 0)
                {
                    node = waitNodeCacheHeader.next;
                    waitNodeCacheHeader.next = node.next;
                    waitNodeCacheCount--;
                }
                else
                {
                    node = new WaitingThreadNode();
                }

                peekWaitHeader.previous.next = node;
                node.previous = peekWaitHeader.previous;
                peekWaitHeader.previous = node;
                node.next = peekWaitHeader;

                try
                {
                    Monitor.Wait(peekWaitHeader, _millisecondsTimeout);
                }
                catch { }

                if (node.valueReturned)
                {
                    returnValue = node.returnValue;
                    node.returnValue = null;
                    node.valueReturned = false;
                }
                else
                {
                    node.previous.next = node.next;
                    node.next.previous = node.previous;
                    node.previous = null;
                    peekWaitCount--;
                }

                node.next = waitNodeCacheHeader.next;
                waitNodeCacheHeader.next = node;
                waitNodeCacheCount++;
            }
            return returnValue;
        }
Esempio n. 11
0
        /// <summary>
        /// Renders the queue incapable of accepting further input, and immediately
        /// returns null to waiting threads
        /// </summary>
        public override void Close()
        {
            lock (syncObj)
            {
                if (!isOpen)
                {
                    return;
                }
                WaitingThreadNode node;

                if (peekWaitCount > 0)
                {
                    lock (peekWaitHeader)
                    {
                        if (peekWaitCount > 0)
                        {
                            node = peekWaitHeader.next;
                            while (node != peekWaitHeader)
                            {
                                node.valueReturned = true;
                                node.returnValue = null;
                                node.previous = null;
                                node = node.next;
                                node.previous.next = null;
                            }
                            peekWaitCount = 0;
                            peekWaitHeader.next = null;
                            Monitor.PulseAll(peekWaitHeader);
                        }
                    }
                }

                if (removeWaitCount > 0)
                {
                    lock (removeWaitHeader)
                    {
                        if (removeWaitCount > 0)
                        {
                            node = removeWaitHeader.next;
                            WaitingThreadNode[] nodes = new WaitingThreadNode[removeWaitCount];
                            for (int x = 0; x < removeWaitCount; x++)
                            {
                                nodes[x] = node;
                                node.valueReturned = true;
                                node.returnValue = null;
                                node.previous = null;
                                node = node.next;
                                node.previous.next = null;
                            }
                            for (int x = 0; x < removeWaitCount; x++)
                            {
                                lock (nodes[x])
                                {
                                    Monitor.Pulse(nodes[x]);
                                }
                            }
                            removeWaitHeader.next = removeWaitHeader;
                            removeWaitHeader.previous = removeWaitHeader;
                            removeWaitCount = 0;
                        }
                    }
                }

            }
        }
Esempio n. 12
0
        /// <summary>
        /// Adds the specified object to the back of the queue
        /// </summary>
        /// <param name="_object">The object to add</param>
        public override void Add(object _object)
        {
            lock (monitor)
            {
                if (!isOpen)
                {
                    throw new InvalidOperationException("This instance is closed, and cannot accept input");
                }
                else if ((!isNullAllowed) && (_object == null))
                {
                    throw new ArgumentNullException("This instance does not allow null input");
                }

                if (peekWaitCount > 0)
                {
                    lock (peekWaitHeader)
                    {
                        if (peekWaitCount > 0)
                        {
                            WaitingThreadNode node;
                            node = peekWaitHeader.next;
                            while (node != peekWaitHeader)
                            {
                                node.valueReturned = true;
                                node.returnValue   = _object;
                                node.previous      = null;
                                node = node.next;
                                node.previous.next = null;
                            }
                            peekWaitCount       = 0;
                            peekWaitHeader.next = null;
                            Monitor.PulseAll(peekWaitHeader);
                        }
                    }
                }

                if (removeWaitCount > 0)
                {
                    lock (removeWaitHeader)
                    {
                        if (removeWaitCount > 0)
                        {
                            WaitingThreadNode node = removeWaitHeader.next;
                            removeWaitHeader.next          = node.next;
                            removeWaitHeader.next.previous = removeWaitHeader;
                            node.next     = null;
                            node.previous = null;
                            removeWaitCount--;

                            lock (node)
                            {
                                node.valueReturned = true;
                                node.returnValue   = _object;
                                Monitor.Pulse(node);
                            }
                        }
                    }
                }
                else
                {
                    if (count == capacity)
                    {
                        IncreaseArraySize();
                    }
                    if (count > 0)
                    {
                        endIndex++;
                        if (endIndex == capacity)
                        {
                            endIndex = 0;
                        }
                    }
                    elements[endIndex] = _object;
                    count++;
                }
            }
        }
Esempio n. 13
0
        /// <summary>
        /// Removes and returns the object at the back of the queue.  If the queue
        /// is currently empty, waits the specified number of milliseconds for the next
        /// input to the queue
        /// </summary>
        /// <param name="_millisecondsTimeout">The number of milliseconds to wait</param>
        /// <returns>The object at the back of the queue, or null if the queue was initially empty and the timeout expired</returns>
        public object RemoveLast(int _millisecondsTimeout)
        {
            object returnValue = null;

            lock (monitor)
            {
                if (count > 0)
                {
                    returnValue = elements[endIndex--];
                    if (endIndex < 0)
                    {
                        endIndex = capacity - 1;
                    }
                    count--;
                    return(returnValue);
                }

                if ((_millisecondsTimeout <= 0) || (!isOpen))
                {
                    return(null);
                }
            }

            WaitingThreadNode node;

            lock (removeWaitHeader)
            {
                peekWaitCount++;


                if (waitNodeCacheCount > 0)
                {
                    node = waitNodeCacheHeader.next;
                    waitNodeCacheHeader.next = node.next;
                    waitNodeCacheCount--;
                }
                else
                {
                    node = new WaitingThreadNode();
                }

                removeWaitHeader.previous.next = node;
                node.previous             = removeWaitHeader.previous;
                removeWaitHeader.previous = node;
                node.next = removeWaitHeader;
            }

            lock (node)
            {
                if (!node.valueReturned)
                {
                    try
                    {
                        Monitor.Wait(node, _millisecondsTimeout);
                    }
                    catch { }
                }
            }

            lock (removeWaitHeader)
            {
                if (node.valueReturned)
                {
                    returnValue        = node.returnValue;
                    node.returnValue   = null;
                    node.valueReturned = false;
                }
                else
                {
                    node.previous.next = node.next;
                    node.next.previous = node.previous;
                    node.previous      = null;
                    peekWaitCount--;
                }

                node.next = waitNodeCacheHeader.next;
                waitNodeCacheHeader.next = node;
                waitNodeCacheCount++;
            }

            return(returnValue);
        }
Esempio n. 14
0
        /// <summary>
        /// Gets the object at the back of the queue without removing it.  If the queue
        /// is currently empty, waits the specified number of milliseconds for the next
        /// input to the queue
        /// </summary>
        /// <param name="_millisecondsTimeout">The number of milliseconds to wait</param>
        /// <returns>The object at the back of the queue, or null if the queue was initially empty and the timeout expired</returns>
        public object PeekLast(int _millisecondsTimeout)
        {
            lock (monitor)
            {
                if (count > 0)
                {
                    return(elements[endIndex]);
                }
                if ((_millisecondsTimeout <= 0) || (!isOpen))
                {
                    return(null);
                }
            }

            object returnValue = null;

            lock (peekWaitHeader)
            {
                peekWaitCount++;

                WaitingThreadNode node;

                if (waitNodeCacheCount > 0)
                {
                    node = waitNodeCacheHeader.next;
                    waitNodeCacheHeader.next = node.next;
                    waitNodeCacheCount--;
                }
                else
                {
                    node = new WaitingThreadNode();
                }

                peekWaitHeader.previous.next = node;
                node.previous           = peekWaitHeader.previous;
                peekWaitHeader.previous = node;
                node.next = peekWaitHeader;

                try
                {
                    Monitor.Wait(peekWaitHeader, _millisecondsTimeout);
                }
                catch { }

                if (node.valueReturned)
                {
                    returnValue        = node.returnValue;
                    node.returnValue   = null;
                    node.valueReturned = false;
                }
                else
                {
                    node.previous.next = node.next;
                    node.next.previous = node.previous;
                    node.previous      = null;
                    peekWaitCount--;
                }

                node.next = waitNodeCacheHeader.next;
                waitNodeCacheHeader.next = node;
                waitNodeCacheCount++;
            }
            return(returnValue);
        }
Esempio n. 15
0
        /// <summary>
        /// Removes the next (highest-priority) object from the queue, or null if
        /// the queue is initially empty and the specified timeout is reached without
        /// input
        /// </summary>
        /// <param name="_millisecondsTimeout"></param>
        /// <returns>The next object from the highest priority currently contained by the queue</returns>
        public override object Remove(int millisecondsTimeout)
        {
            object returnValue = null;
            lock (syncObj)
            {
                if (count > 0)
                {
                    if (highestPrioritySublist != null)
                    {
                        returnValue = highestPrioritySublist.RemoveFirst();
                        if (highestPrioritySublist.count == 0)
                        {
                            highestPrioritySublist = null;
                        }
                        count--;
                        return returnValue;
                    }
                    else
                    {
                        Sublist sublist;
                        for (int x = (sublistCount - 1); x >= 0; x--)
                        {
                            sublist = sublistArray[x];
                            if (sublist.count > 0)
                            {
                                returnValue = sublist.RemoveFirst();
                                if (sublist.count > 0)
                                {
                                    highestPrioritySublist = sublist;
                                }
                                count--;
                                return returnValue;
                            }
                        }
                    }
                }

                if ((millisecondsTimeout <= 0) || (!isOpen))
                {
                    return null;
                }
            }

            WaitingThreadNode node;

            lock (removeWaitHeader)
            {
                peekWaitCount++;

                if (waitNodeCacheCount > 0)
                {
                    node = waitNodeCacheHeader.next;
                    waitNodeCacheHeader.next = node.next;
                    waitNodeCacheCount--;
                }
                else
                {
                    node = new WaitingThreadNode();
                }

                removeWaitHeader.previous.next = node;
                node.previous = removeWaitHeader.previous;
                removeWaitHeader.previous = node;
                node.next = removeWaitHeader;

            }

            lock (node)
            {
                if (!node.valueReturned)
                {
                    try
                    {
                        Monitor.Wait(node, millisecondsTimeout);
                    }
                    catch { }
                }
            }

            lock (removeWaitHeader)
            {
                if (node.valueReturned)
                {
                    returnValue = node.returnValue;
                    node.returnValue = null;
                    node.valueReturned = false;
                }
                else
                {
                    node.previous.next = node.next;
                    node.next.previous = node.previous;
                    node.previous = null;
                    peekWaitCount--;
                }

                node.next = waitNodeCacheHeader.next;
                waitNodeCacheHeader.next = node;
                waitNodeCacheCount++;

            }

            return returnValue;
        }
Esempio n. 16
0
        /// <summary>
        /// Gets the next (highest-priority) object without removing it from the queue
        /// </summary>
        /// <param name="_millisecondsTimeout">The number of milliseconds to wait for input if the queue is initially empty</param>
        /// <returns>The highest-priority object on the queue, or null if the queue is initially empty and the timeout expires</returns>
        public override object Peek(int millisecondsTimeout)
        {
            lock (syncObj)
            {
                if (count > 0)
                {
                    if (highestPrioritySublist != null)
                    {
                        return highestPrioritySublist.elements[highestPrioritySublist.startIndex];
                    }
                    else
                    {
                        for (int x = (sublistCount - 1); x > 0; x--)
                        {
                            if (sublistArray[x].count > 0)
                            {
                                highestPrioritySublist = sublistArray[x];
                                return highestPrioritySublist.elements[highestPrioritySublist.startIndex];
                            }
                        }
                    }
                }

                if ((millisecondsTimeout <= 0) || (!isOpen))
                {
                    return null;
                }
            }

            object returnValue = null;
            lock (peekWaitHeader)
            {
                peekWaitCount++;

                WaitingThreadNode node;

                if (waitNodeCacheCount > 0)
                {
                    node = waitNodeCacheHeader.next;
                    waitNodeCacheHeader.next = node.next;
                    waitNodeCacheCount--;
                }
                else
                {
                    node = new WaitingThreadNode();
                }

                peekWaitHeader.previous.next = node;
                node.previous = peekWaitHeader.previous;
                peekWaitHeader.previous = node;
                node.next = peekWaitHeader;

                try
                {
                    Monitor.Wait(peekWaitHeader, millisecondsTimeout);
                }
                catch { }

                if (node.valueReturned)
                {
                    returnValue = node.returnValue;
                    node.returnValue = null;
                    node.valueReturned = false;
                }
                else
                {
                    node.previous.next = node.next;
                    node.next.previous = node.previous;
                    node.previous = null;
                    peekWaitCount--;
                }

                node.next = waitNodeCacheHeader.next;
                waitNodeCacheHeader.next = node;
                waitNodeCacheCount++;
            }
            return returnValue;
        }