private long reserveArrayIndex(Marker from, Marker to) { while (true) { long oldVal = state.get(), marker = from.getMarker(oldVal), delta = from.getDelta(oldVal), rc = from.getRc(oldVal), toMarker = to.getMarker(oldVal), toDelta = to.getDelta(oldVal); if (marker == NO_MARKER) return NO_INDEX; // The list is empty. if (delta == MAX_DELTA) return NO_INDEX; // Too many concurrent operations; spurious failure. if (delta == NO_DELTA) return NO_INDEX; // List is drained and recreated concurrently. if (toDelta == NO_DELTA) { // Same for the OTHER list; spurious. // TODO: the fact that concurrent re-creation of other list necessitates full stop is not // ideal... the reason is that the list NOT being re-created still uses the list // being re-created for boundary check; it needs the old value of the other marker. // However, NO_DELTA means the other marker was already set to a new value. For now, // assume concurrent re-creation is rare and the gap before commit is tiny. return NO_INDEX; } assert rc <= delta; // There can never be more concurrent takers than uncommitted ones. long newDelta = incDeltaValue(marker, toMarker, delta); // Increase target list pos. if (newDelta == NO_DELTA) return NO_INDEX; // Target list is being drained. long newVal = from.setRc(from.setDelta(oldVal, newDelta), rc + 1); // Set delta and refcount. if (setState(oldVal, newVal)) return oldVal; } }
private void commitArrayIndex(Marker from, Marker to, long originalMarker) { while (true) { long oldVal = state.get(), rc = from.getRc(oldVal); long newVal = from.setRc(oldVal, rc - 1); // Decrease refcount. assert rc > 0; if (rc == 1) { // We are the last of the concurrent operations to finish. Commit. long marker = from.getMarker(oldVal), delta = from.getDelta(oldVal), otherMarker = to.getMarker(oldVal), otherDelta = to.getDelta(oldVal); assert rc <= delta; // Move marker according to delta, change delta to 0. long newMarker = applyDeltaToMarker(marker, otherMarker, delta); newVal = from.setDelta(from.setMarker(newVal, newMarker), 0); if (otherMarker == NO_MARKER) { // The other list doesn't exist, create it at the first index of our op. assert otherDelta == 0; newVal = to.setMarker(newVal, originalMarker); } else if (otherDelta > 0 && otherDelta != NO_DELTA && applyDeltaToMarker(otherMarker, marker, otherDelta) == NO_MARKER) { // The other list will be exhausted when it commits. Create new one pending that commit. newVal = to.setDelta(to.setMarker(newVal, originalMarker), NO_DELTA); } } if (setState(oldVal, newVal)) return; } }
private long reserveArrayIndex(Marker from, Marker to) { while (true) { long oldVal = state.get(), marker = from.getMarker(oldVal), delta = from.getDelta(oldVal), rc = from.getRc(oldVal), toMarker = to.getMarker(oldVal), toDelta = to.getDelta(oldVal); if (marker == NO_MARKER) return NO_INDEX; // The list is empty. if (delta == MAX_DELTA) return NO_INDEX; // Too many concurrent operations; spurious failure. if (delta == NO_DELTA) return NO_INDEX; // List is drained and recreated concurrently. if (toDelta == NO_DELTA) { // Same for the OTHER list; spurious. // TODO: the fact that concurrent re-creation of other list necessitates full stop is not // ideal... the reason is that the list NOT being re-created still uses the list // being re-created for boundary check; it needs the old value of the other marker. // However, NO_DELTA means the other marker was already set to a new value. For now, // assume concurrent re-creation is rare and the gap before commit is tiny. return NO_INDEX; } assert rc <= delta; // There can never be more concurrent takers than uncommitted ones. long newDelta = incDeltaValue(marker, toMarker, delta); // Increase target list pos. if (newDelta == NO_DELTA) return NO_INDEX; // Target list is being drained. long newVal = from.setRc(from.setDelta(oldVal, newDelta), rc + 1); // Set delta and refcount. if (setState(oldVal, newVal)) return oldVal; } }
private void commitArrayIndex(Marker from, Marker to, long originalMarker) { while (true) { long oldVal = state.get(), rc = from.getRc(oldVal); long newVal = from.setRc(oldVal, rc - 1); // Decrease refcount. assert rc > 0; if (rc == 1) { // We are the last of the concurrent operations to finish. Commit. long marker = from.getMarker(oldVal), delta = from.getDelta(oldVal), otherMarker = to.getMarker(oldVal), otherDelta = to.getDelta(oldVal); assert rc <= delta; // Move marker according to delta, change delta to 0. long newMarker = applyDeltaToMarker(marker, otherMarker, delta); newVal = from.setDelta(from.setMarker(newVal, newMarker), 0); if (otherMarker == NO_MARKER) { // The other list doesn't exist, create it at the first index of our op. assert otherDelta == 0; newVal = to.setMarker(newVal, originalMarker); } else if (otherDelta > 0 && otherDelta != NO_DELTA && applyDeltaToMarker(otherMarker, marker, otherDelta) == NO_MARKER) { // The other list will be exhausted when it commits. Create new one pending that commit. newVal = to.setDelta(to.setMarker(newVal, originalMarker), NO_DELTA); } } if (setState(oldVal, newVal)) return; } }
public String toString(long markers) { return "{" + getMarker(markers) + ", " + getDelta(markers) + ", " + getRc(markers) + "}"; } }
private T takeImpl() { long oldState = reserveArrayIndex(OBJECTS, EMPTY); if (oldState == NO_INDEX) return null; // For whatever reason, reserve failed. long originalMarker = OBJECTS.getMarker(oldState), delta = OBJECTS.getDelta(oldState); int arrayIndex = (int)getArrayIndex(originalMarker, delta); T result = pool[arrayIndex]; if (result == null) { throwError(oldState, arrayIndex, "null"); } pool[arrayIndex] = null; commitArrayIndex(OBJECTS, EMPTY, originalMarker); return result; }
private boolean offerImpl(T t) { long oldState = reserveArrayIndex(EMPTY, OBJECTS); if (oldState == NO_INDEX) return false; // For whatever reason, reserve failed. long originalMarker = EMPTY.getMarker(oldState), delta = EMPTY.getDelta(oldState); int arrayIndex = (int)getArrayIndex(originalMarker, delta); if (pool[arrayIndex] != null) { throwError(oldState, arrayIndex, "non-null"); } pool[arrayIndex] = t; commitArrayIndex(EMPTY, OBJECTS, originalMarker); return true; }
public String toString(long markers) { return "{" + getMarker(markers) + ", " + getDelta(markers) + ", " + getRc(markers) + "}"; } }
private T takeImpl() { long oldState = reserveArrayIndex(OBJECTS, EMPTY); if (oldState == NO_INDEX) return null; // For whatever reason, reserve failed. long originalMarker = OBJECTS.getMarker(oldState), delta = OBJECTS.getDelta(oldState); int arrayIndex = (int)getArrayIndex(originalMarker, delta); T result = pool[arrayIndex]; if (result == null) { throwError(oldState, arrayIndex, "null"); } pool[arrayIndex] = null; commitArrayIndex(OBJECTS, EMPTY, originalMarker); return result; }
private boolean offerImpl(T t) { long oldState = reserveArrayIndex(EMPTY, OBJECTS); if (oldState == NO_INDEX) return false; // For whatever reason, reserve failed. long originalMarker = EMPTY.getMarker(oldState), delta = EMPTY.getDelta(oldState); int arrayIndex = (int)getArrayIndex(originalMarker, delta); if (pool[arrayIndex] != null) { throwError(oldState, arrayIndex, "non-null"); } pool[arrayIndex] = t; commitArrayIndex(EMPTY, OBJECTS, originalMarker); return true; }