/** * Write a reference to the given position * @param offset index into the reference array * @param reference */ protected void writeReference(long offset, Object reference) { assert referenceMessageSize != 0 : "References are not in use"; // Is there a way to compute the element offset once and just // arithmetic? UnsafeRefArrayAccess.spElement(references, UnsafeRefArrayAccess.calcElementOffset(offset), reference); }
private void signalConsumerProgress(long consumerPosition, E[] buffer, long offset) { spElement(buffer, offset, null); soConsumerPosition(consumerPosition + 1); }
@Override public boolean relaxedOffer(E e) { if (null == e) { throw new NullPointerException("Null is not a valid element"); } final E[] buffer = this.buffer; final long mask = this.mask; final long producerIndex = lpProducerIndex(); final long offset = calcElementOffset(producerIndex, mask); if (null != lvElement(buffer, offset)) { return false; } spElement(buffer, offset, e); // single producer, so store ordered is valid. It is also required to correctly publish the element // and for the consumers to pick up the tail value. soProducerIndex(producerIndex + 1); return true; }
@Override public E relaxedPoll() { final E[] buffer = this.buffer; final long cIndex = lpConsumerIndex(); final long offset = calcElementOffset(cIndex); // If we can't see the next available element we can't poll E e = lvElement(buffer, offset); // LoadLoad if (null == e) { return null; } spElement(buffer, offset, null); soConsumerIndex(cIndex + 1); // StoreStore return e; }
@Override public int drain(final Consumer<E> c, final int limit) { final E[] buffer = this.buffer; final long mask = this.mask; final long cIndex = lpConsumerIndex(); for (int i = 0; i < limit; i++) { final long index = cIndex + i; final long offset = calcElementOffset(index, mask); final E e = lvElement(buffer, offset);// LoadLoad if (null == e) { return i; } spElement(buffer, offset, null); soConsumerIndex(index + 1); // ordered store -> atomic and ordered for size() c.accept(e); } return limit; }
spElement(buffer, offset, e);
UnsafeRefArrayAccess.spElement(buffer, elementOffset, e);
@Override public E poll() { // local load of field to avoid repeated loads after volatile reads final long[] lSequenceBuffer = sequenceBuffer; long consumerIndex = lvConsumerIndex();// LoadLoad final long seqOffset = calcSequenceOffset(consumerIndex); final long seq = lvSequence(lSequenceBuffer, seqOffset);// LoadLoad final long delta = seq - (consumerIndex + 1); if (delta < 0) { // queue is empty return null; } // on 64bit(no compressed oops) JVM this is the same as seqOffset final long offset = calcElementOffset(consumerIndex); final E e = UnsafeRefArrayAccess.lpElement(buffer, offset); UnsafeRefArrayAccess.spElement(buffer, offset, null); // Move sequence ahead by capacity, preparing it for next offer // (seeing this value from a consumer will lead to retry 2) soSequence(lSequenceBuffer, seqOffset, consumerIndex + mask + 1);// StoreStore soConsumerIndex(consumerIndex+1); return e; }
@Override public void drain(Consumer<E> c, WaitStrategy w, ExitCondition exit) { final E[] buffer = this.buffer; final long mask = this.mask; long cIndex = lpConsumerIndex(); int counter = 0; while (exit.keepRunning()) { for (int i = 0; i < 4096; i++) { final long offset = calcElementOffset(cIndex, mask); final E e = lvElement(buffer, offset);// LoadLoad if (null == e) { counter = w.idle(counter); continue; } cIndex++; counter = 0; spElement(buffer, offset, null); soConsumerIndex(cIndex); // ordered store -> atomic and ordered for size() c.accept(e); } } }
spElement(buffer, offset, null); soConsumerIndex(cIndex + 1); // StoreStore return e;
@Override public boolean relaxedOffer(E e) { if (null == e) { throw new NullPointerException("Null is not a valid element"); } final E[] buffer = this.buffer; final long mask = this.mask; final long producerIndex = lvProducerIndex(); final long offset = calcElementOffset(producerIndex, mask); if (null != lvElement(buffer, offset)) { return false; } spElement(buffer, offset, e); // single producer, so store ordered is valid. It is also required to correctly publish the element // and for the consumers to pick up the tail value. soProducerIndex(producerIndex + 1); return true; }
@Override public E relaxedPoll() { final E[] buffer = this.buffer; final long cIndex = lpConsumerIndex(); final long offset = calcElementOffset(cIndex); // If we can't see the next available element we can't poll E e = lvElement(buffer, offset); // LoadLoad if (null == e) { return null; } spElement(buffer, offset, null); soConsumerIndex(cIndex + 1); // StoreStore return e; }
spElement(buffer, offset, e);
@Override public int drain(final Consumer<E> c, final int limit) { final E[] buffer = this.buffer; final long mask = this.mask; final long cIndex = lpConsumerIndex(); for (int i = 0; i < limit; i++) { final long index = cIndex + i; final long offset = calcElementOffset(index, mask); final E e = lvElement(buffer, offset);// LoadLoad if (null == e) { return i; } spElement(buffer, offset, null); soConsumerIndex(index + 1); // ordered store -> atomic and ordered for size() c.accept(e); } return limit; }
@Override public void drain(Consumer<E> c, WaitStrategy w, ExitCondition exit) { final E[] buffer = this.buffer; final long mask = this.mask; long cIndex = lpConsumerIndex(); int counter = 0; while (exit.keepRunning()) { for (int i = 0; i < 4096; i++) { final long offset = calcElementOffset(cIndex, mask); final E e = lvElement(buffer, offset);// LoadLoad if (null == e) { counter = w.idle(counter); continue; } cIndex++; counter = 0; spElement(buffer, offset, null); soConsumerIndex(cIndex); // ordered store -> atomic and ordered for size() c.accept(e); } } }
spElement(buffer, offset, null); soConsumerIndex(cIndex + 1); // StoreStore return e;