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 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; } }