/** * Read a reference at the given position * @param offset index into the reference array * @return */ protected Object readReference(long offset) { assert referenceMessageSize != 0 : "References are not in use"; // Is there a way to compute the element offset once and just // arithmetic? return UnsafeRefArrayAccess.lpElement(references, UnsafeRefArrayAccess.calcElementOffset(offset)); }
private boolean addSlowPath(E[] buffer, long mask, E newVal, int hash) { final int limit = (int) (hash + mask); for (int i = hash + 1; i <= limit; i++) { final long offset = calcElementOffset(i, mask); final E currVal = lpElement(buffer, offset); if (currVal == null) { size++; soElement(buffer, offset, newVal); return true; } else if (newVal.equals(currVal)) { return false; } } return false; }
@Override public E relaxedPeek() { long currConsumerIndex = lvConsumerIndex(); return lpElement(buffer, calcElementOffset(currConsumerIndex)); }
private E removeElement(final E[] buffer, long index, final long mask) { final long offset = calcElementOffset(index, mask); // load plain, element happens before it's index becomes visible final E e = lpElement(buffer, offset); // store ordered, make sure nulling out is visible. Producer is waiting for this value. soElement(buffer, offset, null); return e; }
@Override public E peek() { return UnsafeRefArrayAccess.lpElement(buffer, calcElementOffset(lvConsumerIndex())); }
private void addForResize(final E[] buffer, final long mask, E newVal) { final int hash = rehash(newVal.hashCode()); final int limit = (int) (hash + mask); for (int i = hash; i <= limit; i++) { final long offset = calcElementOffset(i, mask); final E currVal = lpElement(buffer, offset); if (currVal == null) { soElement(buffer, offset, newVal); return; } } }
private boolean removeSlowPath(Object val, E[] buffer, long mask, int hash) { final int limit = (int) (hash + mask); for (int searchIndex = hash + 1; searchIndex <= limit; searchIndex++) { final long offset = calcElementOffset(searchIndex, mask); final E e = lpElement(buffer, offset); if (e == null) { return false; } else if (val.equals(e)) { size--; if (lpElement(buffer, calcElementOffset(searchIndex + 1, mask)) == null) { soElement(buffer, offset, null); } else { compactAndRemove(buffer, mask, searchIndex); } return true; } } return false; }
@Override public boolean remove(Object val) { final E[] buffer = this.buffer; final long mask = buffer.length - 1; final int hash = rehash(val.hashCode()); final long offset = calcElementOffset(hash, mask); final E e = lpElement(buffer, offset); if (e == null) { return false; } else if (val.equals(e)) { size--; if (lpElement(buffer, calcElementOffset(hash + 1, mask)) == null) { soElement(buffer, offset, null); } else { compactAndRemove(buffer, mask, hash); } return true; } return removeSlowPath(val, buffer, mask, hash); }
@Override public E peek() { long cIndex; E e; do { cIndex = lvConsumerIndex(); // other consumers may have grabbed the element, or queue might be empty e = lpElement(buffer, calcElementOffset(cIndex)); // only return null if queue is empty } while (e == null && cIndex != lvProducerIndex()); return e; }
@Override public boolean add(E newVal) { final E[] buffer = this.buffer; final long mask = buffer.length - 1; final int hash = rehash(newVal.hashCode()); final long offset = calcElementOffset(hash, mask); final E currVal = lpElement(buffer, offset); boolean result; if (currVal == null) { size++; soElement(buffer, offset, newVal); result = true; } else { result = !newVal.equals(currVal) && addSlowPath(buffer, mask, newVal, hash); } if (result && size > resizeThreshold) { resize(); } return result; }
slotJ = lpElement(buffer, calcElementOffset(j, mask));
@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 E relaxedPoll() { final long[] sBuffer = sequenceBuffer; final long mask = this.mask; long cIndex; long seqOffset; long seq; long expectedSeq; do { cIndex = lvConsumerIndex(); seqOffset = calcSequenceOffset(cIndex, mask); seq = lvSequence(sBuffer, seqOffset); expectedSeq = cIndex + 1; if (seq < expectedSeq) { return null; } } while (seq > expectedSeq || // another consumer beat us to it !casConsumerIndex(cIndex, cIndex + 1)); // failed the CAS final long offset = calcElementOffset(cIndex, mask); final E e = lpElement(buffer, offset); soElement(buffer, offset, null); soSequence(sBuffer, seqOffset, cIndex + mask + 1); return e; }
final E e = lpElement(buffer, offset); soElement(buffer, offset, null); soSequence(sBuffer, seqOffset, index + mask + 1);
final E e = lpElement(buffer, offset); soElement(buffer, offset, null); soSequence(sBuffer, seqOffset, cIndex + mask + 1);
final E e = lpElement(buffer, offset); soElement(buffer, offset, null); soSequence(sBuffer, seqOffset, cIndex + mask + 1);// i.e. seq += capacity
@Override public E relaxedPeek() { long currConsumerIndex = lvConsumerIndex(); return lpElement(buffer, calcElementOffset(currConsumerIndex)); }
private E removeElement(final E[] buffer, long index, final long mask) { final long offset = calcElementOffset(index, mask); // load plain, element happens before it's index becomes visible final E e = lpElement(buffer, offset); // store ordered, make sure nulling out is visible. Producer is waiting for this value. soElement(buffer, offset, null); return e; }
@Override public E peek() { long cIndex; E e; do { cIndex = lvConsumerIndex(); // other consumers may have grabbed the element, or queue might be empty e = lpElement(buffer, calcElementOffset(cIndex)); // only return null if queue is empty } while (e == null && cIndex != lvProducerIndex()); return e; }
@Override public E relaxedPoll() { final long[] sBuffer = sequenceBuffer; final long mask = this.mask; long cIndex; long seqOffset; long seq; long expectedSeq; do { cIndex = lvConsumerIndex(); seqOffset = calcSequenceOffset(cIndex, mask); seq = lvSequence(sBuffer, seqOffset); expectedSeq = cIndex + 1; if (seq < expectedSeq) { return null; } } while (seq > expectedSeq || // another consumer beat us to it !casConsumerIndex(cIndex, cIndex + 1)); // failed the CAS final long offset = calcElementOffset(cIndex, mask); final E e = lpElement(buffer, offset); soElement(buffer, offset, null); soSequence(sBuffer, seqOffset, cIndex + mask + 1); return e; }