* Fixed a bug where the blocking queue was holding up logouts for up to 15 seconds * Client.Self is now updated by terse update messages along with full object updates * Parcel.Update() now takes a bool specifying if we want a confirmation Packet * An optimization has been added to MainAvatarStatus to prevent duplicate AgentUpdate packets from being sent out. If the avatar is staying idle it will use a lot less bandwidth now * Default camera distance is now 384 so we see the entire sim git-svn-id: http://libopenmetaverse.googlecode.com/svn/trunk@1107 52acb1d6-8a22-11de-b505-999d5b087335
179 lines
5.2 KiB
C#
179 lines
5.2 KiB
C#
using System;
|
|
using System.Threading;
|
|
using libsecondlife;
|
|
|
|
namespace System.Collections
|
|
{
|
|
/// <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 : Queue
|
|
{
|
|
private bool open;
|
|
|
|
/// <summary>
|
|
/// Create new BlockingQueue.
|
|
/// </summary>
|
|
/// <param name="col">The System.Collections.ICollection to copy elements from</param>
|
|
public BlockingQueue(ICollection col)
|
|
: base(col)
|
|
{
|
|
open = true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Create new BlockingQueue.
|
|
/// </summary>
|
|
/// <param name="capacity">The initial number of elements that the queue can contain</param>
|
|
/// <param name="growFactor">The factor by which the capacity of the queue is expanded</param>
|
|
public BlockingQueue(int capacity, float growFactor)
|
|
: base(capacity, growFactor)
|
|
{
|
|
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)
|
|
{
|
|
open = true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Create new BlockingQueue.
|
|
/// </summary>
|
|
public BlockingQueue()
|
|
: base()
|
|
{
|
|
open = true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// BlockingQueue Destructor (Close queue, resume any waiting thread).
|
|
/// </summary>
|
|
~BlockingQueue()
|
|
{
|
|
Close();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Remove all objects from the Queue.
|
|
/// </summary>
|
|
public override void Clear()
|
|
{
|
|
lock (base.SyncRoot)
|
|
{
|
|
base.Clear();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Remove all objects from the Queue, resume all dequeue threads.
|
|
/// </summary>
|
|
public void Close()
|
|
{
|
|
lock (base.SyncRoot)
|
|
{
|
|
open = false;
|
|
base.Clear();
|
|
Monitor.PulseAll(base.SyncRoot); // resume any waiting threads
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Removes and returns the object at the beginning of the Queue.
|
|
/// </summary>
|
|
/// <returns>Object in queue.</returns>
|
|
public override object 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 NetworkManager.IncomingPacket 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 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;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds an object to the end of the Queue.
|
|
/// </summary>
|
|
/// <param name="obj">Object to put in queue</param>
|
|
public override void Enqueue(object obj)
|
|
{
|
|
lock (base.SyncRoot)
|
|
{
|
|
base.Enqueue(obj);
|
|
Monitor.Pulse(base.SyncRoot);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Open Queue.
|
|
/// </summary>
|
|
public void Open()
|
|
{
|
|
lock (base.SyncRoot)
|
|
{
|
|
open = true;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets flag indicating if queue has been closed.
|
|
/// </summary>
|
|
public bool Closed
|
|
{
|
|
get { return !open; }
|
|
}
|
|
}
|
|
}
|