Class MpscLinkedQueue<E>

  • Type Parameters:
    E -
    All Implemented Interfaces:
    Iterable<E>, Collection<E>, Queue<E>


    public final class MpscLinkedQueue<E>
    extends AbstractQueue<E>
    This is a direct Java port of the MPSC algorithm as presented on 1024 Cores by D. Vyukov. The original has been adapted to Java and it's quirks with regards to memory model and layout:
    1. Use inheritance to ensure no false sharing occurs between producer/consumer node reference fields.
    2. Use XCHG functionality to the best of the JDK ability (see differences in JDK7/8 impls).
    The queue is initialized with a stub node which is set to both the producer and consumer node references. From this point follow the notes on offer/poll.
    • Field Detail

      • C_NODE_OFFSET

        protected static final long C_NODE_OFFSET
      • P_NODE_OFFSET

        protected static final long P_NODE_OFFSET
    • Constructor Detail

      • MpscLinkedQueue

        public MpscLinkedQueue()
    • Method Detail

      • offer

        public final boolean offer(E nextValue)

        IMPLEMENTATION NOTES:
        Offer is allowed from multiple threads.
        Offer allocates a new node and:

        1. Swaps it atomically with current producer node (only one producer 'wins')
        2. Sets the new node as the node following from the swapped producer node
        This works because each producer is guaranteed to 'plant' a new node and link the old node. No 2 producers can get the same producer node as part of XCHG guarantee.
        See Also:
        MessagePassingQueue.offer(Object), Queue.offer(java.lang.Object)
      • poll

        public final E poll()

        IMPLEMENTATION NOTES:
        Poll is allowed from a SINGLE thread.
        Poll reads the next node from the consumerNode and:

        1. If it is null, the queue is assumed empty (though it might not be).
        2. If it is not null set it as the consumer node and return it's now evacuated value.
        This means the consumerNode.value is always null, which is also the starting point for the queue. Because null values are not allowed to be offered this is the only node with it's value set to null at any one time.
        See Also:
        MessagePassingQueue.poll(), Queue.poll()
      • peek

        public final E peek()
      • iterator

        public final Iterator<E> iterator()
      • isEmpty

        public final boolean isEmpty()

        IMPLEMENTATION NOTES:
        Queue is empty when producerNode is the same as consumerNode. An alternative implementation would be to observe the producerNode.value is null, which also means an empty queue because only the consumerNode.value is allowed to be null.

        Specified by:
        isEmpty in interface  Collection<E>
        Overrides:
        isEmpty in class  AbstractCollection<E>
        See Also:
        MessagePassingQueue.isEmpty()
      • spConsumerNode

        protected final void spConsumerNode(LinkedQueueNode<E> node)
      • spProducerNode

        protected final void spProducerNode(LinkedQueueNode<E> node)