protected MpscLinkedQueueNode <T> GetAndSetTailRef(MpscLinkedQueueNode <T> value)
        {
#pragma warning disable 420
            return(Interlocked.Exchange(ref this.tailRef, value));

#pragma warning restore 420
        }
        public IEnumerator <T> GetEnumerator()
        {
            MpscLinkedQueueNode <T> node = this.PeekNode();

            while (node != null)
            {
                yield return(node.Value);

                node = node.Next;
            }
        }
        /// <summary>
        ///  Returns the node right next to the head, which contains the first element of this queue.
        /// </summary>
        MpscLinkedQueueNode <T> PeekNode()
        {
            MpscLinkedQueueNode <T> head = this.HeadRef;
            MpscLinkedQueueNode <T> next = head.Next;

            if (next == null && head != this.TailRef)
            {
                // if tail != head this is not going to change until consumer makes progress
                // we can avoid reading the head and just spin on next until it shows up
                //
                // See https://github.com/akka/akka/pull/15596
                do
                {
                    next = head.Next;
                }while (next == null);
            }
            return(next);
        }
        public T Dequeue()
        {
            MpscLinkedQueueNode <T> next = this.PeekNode();

            if (next == null)
            {
                return(null);
            }

            // next becomes a new head.
            MpscLinkedQueueNode <T> oldHead = this.HeadRef;

            // todo: research storestore vs loadstore barriers
            // See: http://robsjava.blogspot.com/2013/06/a-faster-volatile.html
            // See: http://psy-lob-saw.blogspot.com/2012/12/atomiclazyset-is-performance-win-for.html
            this.HeadRef = next;

            // Break the linkage between the old head and the new head.
            oldHead.Unlink();

            return(next.ClearMaybe());
        }
        public bool Enqueue(T value)
        {
            Contract.Requires(value != null);

            MpscLinkedQueueNode <T> newTail;
            var node = value as MpscLinkedQueueNode <T>;

            if (node != null)
            {
                newTail      = node;
                newTail.Next = null;
            }
            else
            {
                newTail = new DefaultNode(value);
            }

            MpscLinkedQueueNode <T> oldTail = this.GetAndSetTailRef(newTail);

            oldTail.Next = newTail;
            return(true);
        }
        public T Peek()
        {
            MpscLinkedQueueNode <T> next = this.PeekNode();

            return(next == null ? null : next.Value);
        }