Support returning default values on subsequent calls after recursion detection
This commit is contained in:
@@ -10,7 +10,8 @@ public abstract class NotNullLazyValueWithDefault<T> extends NotNullLazyValueImp
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object recursionDetected() {
|
public Object recursionDetected(boolean firstTime) {
|
||||||
|
if (firstTime) return super.recursionDetected(firstTime);
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,29 +21,41 @@ import org.jetbrains.jet.utils.ExceptionUtils;
|
|||||||
import org.jetbrains.jet.utils.WrappedValues;
|
import org.jetbrains.jet.utils.WrappedValues;
|
||||||
|
|
||||||
public abstract class NullableLazyValueImpl<T> implements NullableLazyValue<T> {
|
public abstract class NullableLazyValueImpl<T> implements NullableLazyValue<T> {
|
||||||
private static final Object NOT_COMPUTED = new Object();
|
private enum State {
|
||||||
private static final Object COMPUTING = new Object();
|
NOT_COMPUTED,
|
||||||
|
COMPUTING,
|
||||||
|
RECURSION_WAS_DETECTED
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private Object value = NOT_COMPUTED;
|
private Object value = State.NOT_COMPUTED;
|
||||||
|
|
||||||
public boolean isComputed() {
|
public boolean isComputed() {
|
||||||
return value != NOT_COMPUTED;
|
return value != State.NOT_COMPUTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T compute() {
|
public T compute() {
|
||||||
if (value == COMPUTING) {
|
if (!(value instanceof State)) {
|
||||||
Object result = recursionDetected();
|
// Computed already
|
||||||
if (result != NOT_COMPUTED) {
|
|
||||||
return WrappedValues.unescapeThrowable(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (value != NOT_COMPUTED) {
|
|
||||||
return WrappedValues.unescapeThrowable(value);
|
return WrappedValues.unescapeThrowable(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
value = COMPUTING;
|
if (value == State.COMPUTING) {
|
||||||
|
Object result = recursionDetected(true);
|
||||||
|
if (result != State.NOT_COMPUTED) {
|
||||||
|
value = State.RECURSION_WAS_DETECTED;
|
||||||
|
return WrappedValues.unescapeThrowable(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (value == State.RECURSION_WAS_DETECTED) {
|
||||||
|
Object result = recursionDetected(false);
|
||||||
|
if (result != State.NOT_COMPUTED) {
|
||||||
|
return WrappedValues.unescapeThrowable(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
value = State.COMPUTING;
|
||||||
try {
|
try {
|
||||||
T typedValue = doCompute();
|
T typedValue = doCompute();
|
||||||
value = typedValue;
|
value = typedValue;
|
||||||
@@ -60,7 +72,7 @@ public abstract class NullableLazyValueImpl<T> implements NullableLazyValue<T> {
|
|||||||
* @return {@code NOT_COMPUTED} to proceed, a value or wrapped exception otherwise, see WrappedValues
|
* @return {@code NOT_COMPUTED} to proceed, a value or wrapped exception otherwise, see WrappedValues
|
||||||
* @throws DO NOT throw exceptions from implementations of this method, instead return WrappedValues.escapeThrowable(exception)
|
* @throws DO NOT throw exceptions from implementations of this method, instead return WrappedValues.escapeThrowable(exception)
|
||||||
*/
|
*/
|
||||||
public Object recursionDetected() {
|
public Object recursionDetected(boolean firstTime) {
|
||||||
return WrappedValues.escapeThrowable(new ReenteringLazyValueComputationException());
|
return WrappedValues.escapeThrowable(new ReenteringLazyValueComputationException());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user