@Override
    public int drain(Consumer<E> c, int limit) {
        if (null == c)
            throw new IllegalArgumentException("c is null");
        if (limit < 0)
            throw new IllegalArgumentException("limit is negative: " + limit);
        if (limit == 0)
            return 0;
        LinkedQueueAtomicNode<E> chaserNode = this.lpConsumerNode();
        for (int i = 0; i < limit; i++) {
            final LinkedQueueAtomicNode<E> nextNode = chaserNode.lvNext();
            if (nextNode == null) {
                return i;
            }
            // we have to null out the value because we are going to hang on to the node
            final E nextValue = getSingleConsumerNodeValue(chaserNode, nextNode);
            chaserNode = nextNode;
            c.accept(nextValue);
        }
        return limit;
    }
{@inheritDoc} <br>
<p>
IMPLEMENTATION NOTES:<br>
Peek is allowed from a SINGLE thread.<br>
Peek is potentially blocking here as the {@link Queue#peek()} does not allow returning {@code null} if the queue is not
empty. This is very different from the original Vyukov guarantees. See {@link #relaxedPeek()} for the original
semantics.<br>
Poll reads the next node from the consumerNode and:
<ol>
<li>If it is {@code null} AND the queue is empty return {@code null}, <b>if queue is not empty spin wait for
value to become visible</b>.
<li>If it is not {@code null} return it's value.
</ol>

@see MessagePassingQueue#peek()
@see java.util.Queue#peek()
jctools-core/src/main/java/org/jctools/queues/atomic/BaseLinkedAtomicQueue.java