// // Author: Carson Jones // Adapted from "Art of Multiprocessor Programming" by Herlihy and Shavit // CS6966 // using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace UnboundedLockFreeQueue { public class UnboundedQueue where T : class { /// /// Class for a queue node. /// public class Node { public T value; public AtomicReference next; public Node(T value) { this.value = value; next = new AtomicReference(null); } } private Node sentinel = new Node(null); private AtomicReference head, tail; public UnboundedQueue() { head = new AtomicReference(sentinel); tail = new AtomicReference(sentinel); } /// /// Enqueues an item to the queue. /// /// The item to enqueue. public void Enq(T value) { Node node = new Node(value); while (true) { Node last = tail.Get(); Node next = last.next.Get(); if (last == tail.Get()) { if (next == null) { if (last.next.CompareAndSet(next, node)) { tail.CompareAndSet(last, node); return; } } else tail.CompareAndSet(last, next); } } } /// /// Dequeues an item from the queue. /// /// The item to dequeue. public T Deq() { while (true) { Node first = head.Get(); Node last = tail.Get(); Node next = first.next.Get(); if (first == head.Get()) { if (first == last) { if (next == null) { throw new EmptyException(); } tail.CompareAndSet(last, next); } else { T value = next.value; if (head.CompareAndSet(first, next)) return value; } } } } /// /// Getter for testing state on the queue. /// public bool IsEmpty { get { Node first = head.Get(); Node next = first.next.Get(); if (next == null) return true; return false; } } } }