From 94f830b9d9e78fb16b8b6d61205d00a92ccf0a59 Mon Sep 17 00:00:00 2001 From: John Hurliman Date: Thu, 1 Apr 2010 01:07:50 +0000 Subject: [PATCH] * Cleaned up the LocklessQueue implementation, removed the unsafe Clear() method, and added documentation git-svn-id: http://libopenmetaverse.googlecode.com/svn/libopenmetaverse/trunk@3296 52acb1d6-8a22-11de-b505-999d5b087335 --- OpenMetaverse/Simulator.cs | 6 +- OpenMetaverseTypes/LocklessQueue.cs | 110 ++++++++++++++++------------ 2 files changed, 67 insertions(+), 49 deletions(-) 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)