Lazy values: change encoding, now NOT_COMPUTED is an explicit object, and null is stored as such
This commit is contained in:
+9
-8
@@ -114,7 +114,7 @@ public class LockBasedStorageManager implements StorageManager {
|
||||
return new LockBasedLazyValue<T>(lock, computable) {
|
||||
@Override
|
||||
protected Object recursionDetected() {
|
||||
return WrappedValues.escapeNull(onRecursiveCall);
|
||||
return onRecursiveCall;
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -141,13 +141,14 @@ public class LockBasedStorageManager implements StorageManager {
|
||||
|
||||
private static class LockBasedLazyValue<T> implements NullableLazyValue<T> {
|
||||
|
||||
private static final Object NOT_COMPUTED = new Object();
|
||||
private static final Object COMPUTING = new Object();
|
||||
|
||||
private final Object lock;
|
||||
private final Computable<T> computable;
|
||||
|
||||
@Nullable
|
||||
private volatile Object value = null;
|
||||
private volatile Object value = NOT_COMPUTED;
|
||||
|
||||
public LockBasedLazyValue(@NotNull Object lock, @NotNull Computable<T> computable) {
|
||||
this.lock = lock;
|
||||
@@ -157,23 +158,23 @@ public class LockBasedStorageManager implements StorageManager {
|
||||
@Override
|
||||
public T compute() {
|
||||
Object _value = value;
|
||||
if (_value != null && _value != COMPUTING) return WrappedValues.unescapeExceptionOrNull(_value);
|
||||
if (_value != NOT_COMPUTED && _value != COMPUTING) return WrappedValues.unescapeThrowable(_value);
|
||||
|
||||
synchronized (lock) {
|
||||
_value = value;
|
||||
if (_value == COMPUTING) {
|
||||
Object result = recursionDetected();
|
||||
if (result != null) {
|
||||
return WrappedValues.unescapeExceptionOrNull(result);
|
||||
if (result != NOT_COMPUTED) {
|
||||
return WrappedValues.unescapeThrowable(result);
|
||||
}
|
||||
}
|
||||
|
||||
if (_value != null) return WrappedValues.unescapeExceptionOrNull(_value);
|
||||
if (_value != NOT_COMPUTED) return WrappedValues.unescapeThrowable(_value);
|
||||
|
||||
value = COMPUTING;
|
||||
try {
|
||||
T typedValue = computable.compute();
|
||||
value = WrappedValues.escapeNull(typedValue);
|
||||
value = typedValue;
|
||||
postCompute(typedValue);
|
||||
return typedValue;
|
||||
}
|
||||
@@ -185,7 +186,7 @@ public class LockBasedStorageManager implements StorageManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@code null} to proceed, a wrapped value 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)
|
||||
*/
|
||||
@Nullable
|
||||
|
||||
+2
-3
@@ -44,9 +44,8 @@ public interface StorageManager {
|
||||
|
||||
/**
|
||||
* @param onRecursiveCall is called if the computation calls itself recursively.
|
||||
* If this parameter is null, an exception will be thrown on a recursive call.
|
||||
* If this function returns null, the computation proceeds recursively,
|
||||
* otherwise it should return a result of WrappedValues.escape*() method
|
||||
* If this parameter is null, an exception will be thrown on a recursive call,
|
||||
* otherwise it should return a result of WrappedValues.escapeThrowable() method
|
||||
* @param postCompute is called after the value is computed, but before any other thread sees it (the current thread may
|
||||
* see it in between)
|
||||
*/
|
||||
|
||||
@@ -58,10 +58,16 @@ public class WrappedValues {
|
||||
|
||||
@Nullable
|
||||
public static <V> V unescapeExceptionOrNull(@NotNull Object value) {
|
||||
return unescapeNull(unescapeThrowable(value));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static <V> V unescapeThrowable(@Nullable Object value) {
|
||||
if (value instanceof ThrowableWrapper) {
|
||||
throw ExceptionUtils.rethrow(((ThrowableWrapper) value).getThrowable());
|
||||
}
|
||||
|
||||
return unescapeNull(value);
|
||||
//noinspection unchecked
|
||||
return (V) value;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user