diff --git a/OpenMetaverse/Simulator.cs b/OpenMetaverse/Simulator.cs
index 9d8725a8..87103148 100644
--- a/OpenMetaverse/Simulator.cs
+++ b/OpenMetaverse/Simulator.cs
@@ -766,7 +766,7 @@ namespace OpenMetaverse
// no more ACKs to append
uint ackCount = 0;
uint ack;
- while (dataLength + 5 < Packet.MTU && PendingAcks.Dequeue(out ack))
+ while (dataLength + 5 < Packet.MTU && PendingAcks.TryDequeue(out ack))
{
Utils.UIntToBytesBig(ack, buffer.Data, dataLength);
dataLength += 4;
@@ -1023,7 +1023,7 @@ namespace OpenMetaverse
{
uint ack;
- if (PendingAcks.Dequeue(out ack))
+ if (PendingAcks.TryDequeue(out ack))
{
Interlocked.Decrement(ref PendingAckCount);
@@ -1032,7 +1032,7 @@ namespace OpenMetaverse
block.ID = ack;
blocks.Add(block);
- while (PendingAcks.Dequeue(out ack))
+ while (PendingAcks.TryDequeue(out ack))
{
Interlocked.Decrement(ref PendingAckCount);
diff --git a/OpenMetaverseTypes/LocklessQueue.cs b/OpenMetaverseTypes/LocklessQueue.cs
index 420a04a1..85c9f803 100644
--- a/OpenMetaverseTypes/LocklessQueue.cs
+++ b/OpenMetaverseTypes/LocklessQueue.cs
@@ -29,95 +29,113 @@ using System.Threading;
namespace OpenMetaverse
{
+ ///
+ /// A thread-safe lockless queue that supports multiple readers and
+ /// multiple writers
+ ///
public sealed class LocklessQueue
{
+ ///
+ /// Provides a node container for data in a singly linked list
+ ///
private sealed class SingleLinkNode
{
+ /// Pointer to the next node in list
public SingleLinkNode Next;
+ /// The data contained by the node
public T Item;
+
+ ///
+ /// Constructor
+ ///
+ public SingleLinkNode() { }
+
+ ///
+ /// Constructor
+ ///
+ public SingleLinkNode(T item)
+ {
+ this.Item = item;
+ }
}
+ /// Queue head
SingleLinkNode head;
+ /// Queue tail
SingleLinkNode tail;
+ /// Queue item count
int count;
+ /// Gets the current number of items in the queue. Since this
+ /// is a lockless collection this value should be treated as a close
+ /// estimate
public int Count { get { return count; } }
+ ///
+ /// Constructor
+ ///
public LocklessQueue()
{
- Init();
+ count = 0;
+ head = tail = new SingleLinkNode();
}
+ ///
+ /// Enqueue an item
+ ///
+ /// Item to enqeue
public void Enqueue(T item)
{
- SingleLinkNode oldTail = null;
- SingleLinkNode oldTailNext;
+ SingleLinkNode newNode = new SingleLinkNode { Item = item };
- SingleLinkNode newNode = new SingleLinkNode();
- newNode.Item = item;
-
- bool newNodeWasAdded = false;
-
- while (!newNodeWasAdded)
+ while (true)
{
- oldTail = tail;
- oldTailNext = oldTail.Next;
+ SingleLinkNode oldTail = tail;
+ SingleLinkNode oldTailNext = oldTail.Next;
if (tail == oldTail)
{
- if (oldTailNext == null)
- newNodeWasAdded = CAS(ref tail.Next, null, newNode);
- else
+ if (oldTailNext != null)
+ {
CAS(ref tail, oldTail, oldTailNext);
+ }
+ else if (CAS(ref tail.Next, null, newNode))
+ {
+ CAS(ref tail, oldTail, newNode);
+ Interlocked.Increment(ref count);
+ return;
+ }
}
}
-
- CAS(ref tail, oldTail, newNode);
- Interlocked.Increment(ref count);
}
- public bool Dequeue(out T item)
+ ///
+ /// Try to dequeue an item
+ ///
+ /// Dequeued item if the dequeue was successful
+ /// True if an item was successfully deqeued, otherwise false
+ public bool TryDequeue(out T item)
{
- item = default(T);
- SingleLinkNode oldHead = null;
- bool haveAdvancedHead = false;
-
- while (!haveAdvancedHead)
+ while (true)
{
- oldHead = head;
- SingleLinkNode oldTail = tail;
+ SingleLinkNode oldHead = head;
SingleLinkNode oldHeadNext = oldHead.Next;
if (oldHead == head)
{
- if (oldHead == oldTail)
+ if (oldHeadNext == null)
{
- if (oldHeadNext == null)
- return false;
-
- CAS(ref tail, oldTail, oldHeadNext);
+ item = default(T);
+ return false;
}
- else
+ if (CAS(ref head, oldHead, oldHeadNext))
{
item = oldHeadNext.Item;
- haveAdvancedHead = CAS(ref head, oldHead, oldHeadNext);
+ Interlocked.Decrement(ref count);
+ return true;
}
}
}
-
- Interlocked.Decrement(ref count);
- return true;
- }
-
- public void Clear()
- {
- Init();
- }
-
- private void Init()
- {
- count = 0;
- head = tail = new SingleLinkNode();
}
private static bool CAS(ref SingleLinkNode location, SingleLinkNode comparand, SingleLinkNode newValue)