public boolean offer(final E e) { if (null == e) { throw new NullPointerException("element cannot be null"); } long currentTail; long currentHead = sharedHeadCache; long bufferLimit = currentHead + capacity; do { currentTail = tail; if (currentTail >= bufferLimit) { currentHead = head; bufferLimit = currentHead + capacity; if (currentTail >= bufferLimit) { return false; } UNSAFE.putOrderedLong(this, SHARED_HEAD_CACHE_OFFSET, currentHead); } } while (!UNSAFE.compareAndSwapLong(this, TAIL_OFFSET, currentTail, currentTail + 1)); UNSAFE.putOrderedObject(buffer, sequenceToBufferOffset(currentTail, mask), e); return true; }
@SuppressWarnings("unchecked") public E poll() { final long currentHead = head; final long elementOffset = sequenceToBufferOffset(currentHead, mask); final Object[] buffer = this.buffer; final Object e = UNSAFE.getObjectVolatile(buffer, elementOffset); if (null != e) { UNSAFE.putObject(buffer, elementOffset, null); UNSAFE.putOrderedLong(this, HEAD_OFFSET, currentHead + 1); } return (E) e; }
@SuppressWarnings("unchecked") public int drainTo(final Collection<? super E> target, final int limit) { final Object[] buffer = this.buffer; final long mask = this.mask; long nextSequence = head; int count = 0; while (count < limit) { final long elementOffset = sequenceToBufferOffset(nextSequence, mask); final Object e = UNSAFE.getObjectVolatile(buffer, elementOffset); if (null == e) { break; } UNSAFE.putOrderedObject(buffer, elementOffset, null); nextSequence++; UNSAFE.putOrderedLong(this, HEAD_OFFSET, nextSequence); count++; target.add((E) e); } return count; }
@SuppressWarnings("unchecked") public int drain(final Consumer<E> elementHandler) { final Object[] buffer = this.buffer; final long mask = this.mask; final long currentHead = head; long nextSequence = currentHead; final long limit = nextSequence + mask + 1; while (nextSequence < limit) { final long elementOffset = sequenceToBufferOffset(nextSequence, mask); final Object item = UNSAFE.getObjectVolatile(buffer, elementOffset); if (null == item) { break; } UNSAFE.putOrderedObject(buffer, elementOffset, null); nextSequence++; UNSAFE.putOrderedLong(this, HEAD_OFFSET, nextSequence); elementHandler.accept((E) item); } return (int) (nextSequence - currentHead); }
protected final void soTail(long v) { UNSAFE.putOrderedLong(this, P_INDEX_OFFSET, v); }