/// <summary> /// Enqueues the specified item. /// </summary> /// <param name="item">The item.</param> public void Enqueue(T item) { SingleLinkedNode <T> oldTail = null; var node = new SingleLinkedNode <T> { Item = item }; // Loop until we have managed to update the tail's Next link to point to our new node. var updatedNewLink = false; while (!updatedNewLink) { // Make local copies of the tail and its Next link, but in getting the latter use the local copy of // the tail since another thread may have changed the value of tail. oldTail = tail; var oldNext = oldTail.Next; // Providing that the tail field has not changed... if (tail == oldTail) { // ...and its Next field is null... if (oldNext == null) { // ...try to update the tail's Next field. updatedNewLink = null == Interlocked.CompareExchange(ref tail.Next, node, null); } else { // If the tail's Next field was non-null, another thread is in the middle of enqueuing a new node, so try and // advance the tail to point to its Next node. Interlocked.CompareExchange(ref tail, oldNext, oldTail); } } } // Try and update the tail field to point to our node; Don't worry if we can't, another thread will update it for us on // the next call to Enqueue(). Interlocked.CompareExchange(ref tail, node, oldTail); Interlocked.Increment(ref count); }
/// <summary> /// Initializes a new instance of the <see cref="LockFreeQueue<T>" /> class. /// </summary> public LockFreeQueue() { head = new SingleLinkedNode <T>(); tail = head; }