From 7dfe1f963dd61d84fedb3cc74e426de6a068aeca Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Wed, 2 Oct 2013 12:42:21 +0400 Subject: [PATCH] Support returning default values on subsequent calls after recursion detection --- .../storage/NotNullLazyValueWithDefault.java | 3 +- .../jet/storage/NullableLazyValueImpl.java | 38 ++++++++++++------- 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/core/util.runtime/src/org/jetbrains/jet/storage/NotNullLazyValueWithDefault.java b/core/util.runtime/src/org/jetbrains/jet/storage/NotNullLazyValueWithDefault.java index 3feae710d53..5d00fe0f41c 100644 --- a/core/util.runtime/src/org/jetbrains/jet/storage/NotNullLazyValueWithDefault.java +++ b/core/util.runtime/src/org/jetbrains/jet/storage/NotNullLazyValueWithDefault.java @@ -10,7 +10,8 @@ public abstract class NotNullLazyValueWithDefault extends NotNullLazyValueImp } @Override - public Object recursionDetected() { + public Object recursionDetected(boolean firstTime) { + if (firstTime) return super.recursionDetected(firstTime); return defaultValue; } } diff --git a/core/util.runtime/src/org/jetbrains/jet/storage/NullableLazyValueImpl.java b/core/util.runtime/src/org/jetbrains/jet/storage/NullableLazyValueImpl.java index 8c0a75da66b..50500a146e9 100644 --- a/core/util.runtime/src/org/jetbrains/jet/storage/NullableLazyValueImpl.java +++ b/core/util.runtime/src/org/jetbrains/jet/storage/NullableLazyValueImpl.java @@ -21,29 +21,41 @@ import org.jetbrains.jet.utils.ExceptionUtils; import org.jetbrains.jet.utils.WrappedValues; public abstract class NullableLazyValueImpl implements NullableLazyValue { - private static final Object NOT_COMPUTED = new Object(); - private static final Object COMPUTING = new Object(); + private enum State { + NOT_COMPUTED, + COMPUTING, + RECURSION_WAS_DETECTED + } @Nullable - private Object value = NOT_COMPUTED; + private Object value = State.NOT_COMPUTED; public boolean isComputed() { - return value != NOT_COMPUTED; + return value != State.NOT_COMPUTED; } @Override public T compute() { - if (value == COMPUTING) { - Object result = recursionDetected(); - if (result != NOT_COMPUTED) { - return WrappedValues.unescapeThrowable(result); - } - } - else if (value != NOT_COMPUTED) { + if (!(value instanceof State)) { + // Computed already 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 { T typedValue = doCompute(); value = typedValue; @@ -60,7 +72,7 @@ public abstract class NullableLazyValueImpl implements NullableLazyValue { * @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) */ - public Object recursionDetected() { + public Object recursionDetected(boolean firstTime) { return WrappedValues.escapeThrowable(new ReenteringLazyValueComputationException()); }