corrade-vassal – Rev 1
?pathlinks?
/*
* Copyright (c) 2006-2014, openmetaverse.org
* 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 openmetaverse.org 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.Collections.Generic;
using System.Threading;
using OpenMetaverse;
namespace OpenMetaverse
{
/// <summary>
/// Same as Queue except Dequeue function blocks until there is an object to return.
/// Note: This class does not need to be synchronized
/// </summary>
public class BlockingQueue<T> : Queue<T>
{
private object SyncRoot;
private bool open;
/// <summary>
/// Create new BlockingQueue.
/// </summary>
/// <param name="col">The System.Collections.ICollection to copy elements from</param>
public BlockingQueue(IEnumerable<T> col)
: base(col)
{
SyncRoot = new object();
open = true;
}
/// <summary>
/// Create new BlockingQueue.
/// </summary>
/// <param name="capacity">The initial number of elements that the queue can contain</param>
public BlockingQueue(int capacity)
: base(capacity)
{
SyncRoot = new object();
open = true;
}
/// <summary>
/// Create new BlockingQueue.
/// </summary>
public BlockingQueue()
: base()
{
SyncRoot = new object();
open = true;
}
/// <summary>
/// BlockingQueue Destructor (Close queue, resume any waiting thread).
/// </summary>
~BlockingQueue()
{
Close();
}
/// <summary>
/// Remove all objects from the Queue.
/// </summary>
public new void Clear()
{
lock (SyncRoot)
{
base.Clear();
}
}
/// <summary>
/// Remove all objects from the Queue, resume all dequeue threads.
/// </summary>
public void Close()
{
lock (SyncRoot)
{
open = false;
base.Clear();
Monitor.PulseAll(SyncRoot); // resume any waiting threads
}
}
/// <summary>
/// Removes and returns the object at the beginning of the Queue.
/// </summary>
/// <returns>Object in queue.</returns>
public new T Dequeue()
{
return Dequeue(Timeout.Infinite);
}
/// <summary>
/// Removes and returns the object at the beginning of the Queue.
/// </summary>
/// <param name="timeout">time to wait before returning</param>
/// <returns>Object in queue.</returns>
public T Dequeue(TimeSpan timeout)
{
return Dequeue(timeout.Milliseconds);
}
/// <summary>
/// Removes and returns the object at the beginning of the Queue.
/// </summary>
/// <param name="timeout">time to wait before returning (in milliseconds)</param>
/// <returns>Object in queue.</returns>
public T Dequeue(int timeout)
{
lock (SyncRoot)
{
while (open && (base.Count == 0))
{
if (!Monitor.Wait(SyncRoot, timeout))
throw new InvalidOperationException("Timeout");
}
if (open)
return base.Dequeue();
else
throw new InvalidOperationException("Queue Closed");
}
}
public bool Dequeue(int timeout, ref T obj)
{
lock (SyncRoot)
{
while (open && (base.Count == 0))
{
if (!Monitor.Wait(SyncRoot, timeout))
return false;
}
if (open)
{
obj = base.Dequeue();
return true;
}
else
{
obj = default(T);
return false;
}
}
}
/// <summary>
/// Adds an object to the end of the Queue
/// </summary>
/// <param name="obj">Object to put in queue</param>
public new void Enqueue(T obj)
{
lock (SyncRoot)
{
base.Enqueue(obj);
Monitor.Pulse(SyncRoot);
}
}
/// <summary>
/// Open Queue.
/// </summary>
public void Open()
{
lock (SyncRoot)
{
open = true;
}
}
/// <summary>
/// Gets flag indicating if queue has been closed.
/// </summary>
public bool Closed
{
get { return !open; }
}
}
}