/// <summary> /// Add a node into the list. The function updates the next of the node to the current head /// and replace the head with itself. If the head value read was stale then it resets /// the next until it obtains the current value. /// </summary> /// <param name="node"></param> /// <returns></returns> InterlockedListEntry <T> Add(ref InterlockedListEntry <T> node) { if (node == null) { throw new ArgumentNullException("node"); } if (node.Next != null) { throw new ArgumentException("Node already points to an entry. Ensure that that node does not belong to another list."); } InterlockedListEntry <T> nextSlot = this.head; node.Next = nextSlot; while (true) { if (nextSlot == (nextSlot = Interlocked.CompareExchange(ref this.head, node, nextSlot))) { return(this.head); } else { // Set the next only in the failed case. The node could have been already removed. // and node.next could have become null and we don't want to overwrite it in that case. node.Link(ref nextSlot); } } }
public void Add(T value) { InterlockedListEntry <T> node = new InterlockedListEntry <T>(); node.Value = value; this.Add(ref node); }
/// <summary> /// Removes a node from the list and sets the head to its next pointer. /// If the remove reads a tail value then it returns false indicating that there is /// no value in the list. /// </summary> /// <param name="node"></param> /// <returns></returns> bool RemoveNode(out InterlockedListEntry <T> node) { node = this.head; while (true) { if (node == (node = Interlocked.CompareExchange(ref this.head, node.Next, node))) { if (node != Tail) { node.Unlink(); return(true); } else { return(false); } } } }
public InterlockedList() { this.head = Tail; }
static InterlockedList() { Tail = TailListEntry.Instance; }
public void Link(ref InterlockedListEntry <U> next) { this.Next = next; }
public void Unlink() { this.Next = null; }