@Override
    public void drain(final Consumer<E> c, final WaitStrategy w, final ExitCondition exit) {
        if (null == c)
            throw new IllegalArgumentException("c is null");
        if (null == w)
            throw new IllegalArgumentException("wait is null");
        if (null == exit)
            throw new IllegalArgumentException("exit condition is null");
        final AtomicReferenceArray<E> buffer = this.buffer;
        final int mask = this.mask;
        long consumerIndex = this.lpConsumerIndex();
        int counter = 0;
        while (exit.keepRunning()) {
            for (int i = 0; i < 4096; i++) {
                final int offset = calcCircularRefElementOffset(consumerIndex, mask);
                final E e = lvRefElement(buffer, offset);
                if (null == e) {
                    counter = w.idle(counter);
                    continue;
                }
                consumerIndex++;
                counter = 0;
                soRefElement(buffer, offset, null);
                // ordered store -> atomic and ordered for size()
                soConsumerIndex(consumerIndex);
                c.accept(e);
            }
        }
    }
{@inheritDoc}
<p>
This implementation is correct for single consumer thread use only.
jctools-core/src/main/java/org/jctools/queues/atomic/unpadded/SpscAtomicUnpaddedArrayQueue.java