/* * Copyright (c) 2006-2007, Second Life Reverse Engineering Team * All rights reserved. * * - Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * - Neither the name of the Second Life Reverse Engineering Team nor the names * of its contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ using System; using System.Threading; using libsecondlife; namespace System.Collections { /// /// Same as Queue except Dequeue function blocks until there is an object to return. /// Note: This class does not need to be synchronized /// public class BlockingQueue : Queue { private bool open; /// /// Create new BlockingQueue. /// /// The System.Collections.ICollection to copy elements from public BlockingQueue(ICollection col) : base(col) { open = true; } /// /// Create new BlockingQueue. /// /// The initial number of elements that the queue can contain /// The factor by which the capacity of the queue is expanded public BlockingQueue(int capacity, float growFactor) : base(capacity, growFactor) { open = true; } /// /// Create new BlockingQueue. /// /// The initial number of elements that the queue can contain public BlockingQueue(int capacity) : base(capacity) { open = true; } /// /// Create new BlockingQueue. /// public BlockingQueue() : base() { open = true; } /// /// BlockingQueue Destructor (Close queue, resume any waiting thread). /// ~BlockingQueue() { Close(); } /// /// Remove all objects from the Queue. /// public override void Clear() { lock (base.SyncRoot) { base.Clear(); } } /// /// Remove all objects from the Queue, resume all dequeue threads. /// public void Close() { lock (base.SyncRoot) { open = false; base.Clear(); Monitor.PulseAll(base.SyncRoot); // resume any waiting threads } } /// /// Removes and returns the object at the beginning of the Queue. /// /// Object in queue. public override object Dequeue() { return Dequeue(Timeout.Infinite); } /// /// Removes and returns the object at the beginning of the Queue. /// /// time to wait before returning /// Object in queue. public NetworkManager.IncomingPacket Dequeue(TimeSpan timeout) { return Dequeue(timeout.Milliseconds); } /// /// Removes and returns the object at the beginning of the Queue. /// /// time to wait before returning (in milliseconds) /// Object in queue. public NetworkManager.IncomingPacket Dequeue(int timeout) { lock (base.SyncRoot) { while (open && (base.Count == 0)) { if (!Monitor.Wait(base.SyncRoot, timeout)) throw new InvalidOperationException("Timeout"); } if (open) return (NetworkManager.IncomingPacket)base.Dequeue(); else throw new InvalidOperationException("Queue Closed"); } } public bool Dequeue(int timeout, ref NetworkManager.IncomingPacket packet) { lock (base.SyncRoot) { while (open && (base.Count == 0)) { if (!Monitor.Wait(base.SyncRoot, timeout)) return false; } if (open) { packet = (NetworkManager.IncomingPacket)base.Dequeue(); return true; } else return false; } } /// /// Adds an object to the end of the Queue. /// /// Object to put in queue public override void Enqueue(object obj) { lock (base.SyncRoot) { base.Enqueue(obj); Monitor.Pulse(base.SyncRoot); } } /// /// Open Queue. /// public void Open() { lock (base.SyncRoot) { open = true; } } /// /// Gets flag indicating if queue has been closed. /// public bool Closed { get { return !open; } } } }