Testing a Non-blocking Queue

Posted by jsw on Stack Overflow See other posts from Stack Overflow or by jsw
Published on 2010-04-19T18:59:20Z Indexed on 2010/04/19 19:03 UTC
Read the original article Hit count: 337

Filed under:
|
|
|
|

I've ported the non-blocking queue psuedocode here to C#. The code below is meant as a near verbatim copy of the paper.

What approach would you take to test the implementation?

Note: I'm running in VS2010 so I don't have CHESS support yet.

using System.Threading;

#pragma warning disable 0420

namespace ConcurrentCollections
{
    class QueueNodePointer<T>
    {
        internal QueueNode<T> ptr;
        internal QueueNodePointer() : this(null) { }
        internal QueueNodePointer(QueueNode<T> ptr) { this.ptr = ptr; }
    }

    class QueueNode<T>
    {
        internal T value;
        internal QueueNodePointer<T> next;
        internal QueueNode() : this(default(T)) { }
        internal QueueNode(T value) { this.value = value; this.next = new QueueNodePointer<T>(); }
    }

    public class ConcurrentQueue<T>
    {
        private volatile int count = 0;

        private QueueNodePointer<T> qhead = new QueueNodePointer<T>();
        private QueueNodePointer<T> qtail = new QueueNodePointer<T>();

        public ConcurrentQueue()
        {
            var node = new QueueNode<T>();
            node.next.ptr = null;
            this.qhead.ptr = this.qtail.ptr = node;
        }

        public int Count { get { return this.count; } }

        public void Enqueue(T value)
        {
            var node = new QueueNode<T>(value);
            node.next.ptr = null;

            QueueNodePointer<T> tail;
            QueueNodePointer<T> next;

            while (true)
            {
                tail = this.qtail;
                next = tail.ptr.next;
                if (tail == this.qtail)
                {
                    if (next.ptr == null)
                    {
                        var newtail = new QueueNodePointer<T>(node);
                        if (Interlocked.CompareExchange(ref tail.ptr.next, newtail, next) == next)
                        {
                            Interlocked.Increment(ref this.count);
                            break;
                        }
                        else
                        {
                            Interlocked.CompareExchange(ref this.qtail, new QueueNodePointer<T>(next.ptr), tail);
                        }
                    }
                }
            }

            Interlocked.CompareExchange(ref this.qtail, new QueueNodePointer<T>(node), tail);
        }

        public T Dequeue()
        {
            T value;

            while (true)
            {
                var head = this.qhead;
                var tail = this.qtail;
                var next = head.ptr.next;
                if (head == this.qhead)
                {
                    if (head.ptr == tail.ptr)
                    {
                        if (next.ptr == null)
                        {
                            return default(T);
                        }

                        Interlocked.CompareExchange(ref this.qtail, new QueueNodePointer<T>(next.ptr), tail);
                    }
                    else
                    {
                        value = next.ptr.value;
                        var newhead = new QueueNodePointer<T>(next.ptr);
                        if (Interlocked.CompareExchange(ref this.qhead, newhead, head) == head)
                        {
                            Interlocked.Decrement(ref this.count);
                            break;
                        }
                    }
                }
            }

            return value;
        }
    }
}

#pragma warning restore 0420

© Stack Overflow or respective owner

Related posts about testing

Related posts about nonblocking