Recursion-tolerant notnull lazy values

This commit is contained in:
Andrey Breslav
2013-09-26 12:59:31 -07:00
parent bbdff45246
commit 51dfdf795f
3 changed files with 51 additions and 9 deletions
@@ -49,6 +49,7 @@ import org.jetbrains.jet.lang.resolve.scopes.*;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeConstructor;
import org.jetbrains.jet.lang.types.TypeUtils;
import org.jetbrains.jet.utils.WrappedValues;
import java.util.*;
@@ -395,6 +396,12 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements LazyDesc
}
}
},
new Computable<Object>() {
@Override
public Object compute() {
return WrappedValues.unescapeExceptionOrNull(Collections.emptyList());
}
},
new Consumer<Collection<JetType>>() {
@Override
public void consume(@NotNull Collection<JetType> supertypes) {
@@ -67,8 +67,34 @@ public class LockBasedStorageManager implements StorageManager {
@NotNull
@Override
public <T> NotNullLazyValue<T> createLazyValueWithPostCompute(@NotNull Computable<T> computable, @NotNull final Consumer<T> postCompute) {
public <T> NotNullLazyValue<T> createRecursionTolerantLazyValue(
@NotNull Computable<T> computable, @NotNull final T onRecursiveCall
) {
return new LockBasedNotNullLazyValue<T>(lock, computable) {
@Override
protected Object recursionDetected() {
return onRecursiveCall;
}
};
}
@NotNull
@Override
public <T> NotNullLazyValue<T> createLazyValueWithPostCompute(
@NotNull Computable<T> computable,
final Computable<Object> onRecursiveCall,
@NotNull final Consumer<T> postCompute
) {
return new LockBasedNotNullLazyValue<T>(lock, computable) {
@Nullable
@Override
protected Object recursionDetected() {
if (onRecursiveCall == null) {
return super.recursionDetected();
}
return onRecursiveCall.compute();
}
@Override
protected void postCompute(@NotNull T value) {
postCompute.consume(value);
@@ -84,11 +110,11 @@ public class LockBasedStorageManager implements StorageManager {
@NotNull
@Override
public <T> NullableLazyValue<T> createRecursionTolerantNullableLazyValue(@NotNull Computable<T> computable) {
public <T> NullableLazyValue<T> createRecursionTolerantNullableLazyValue(@NotNull Computable<T> computable, final T onRecursiveCall) {
return new LockBasedLazyValue<T>(lock, computable) {
@Override
protected Object recursionDetected() {
return WrappedValues.escapeNull(null);
return WrappedValues.escapeNull(onRecursiveCall);
}
};
}
@@ -20,6 +20,7 @@ import com.intellij.openapi.util.Computable;
import com.intellij.util.Consumer;
import com.intellij.util.Function;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public interface StorageManager {
/**
@@ -38,21 +39,29 @@ public interface StorageManager {
@NotNull
<T> NotNullLazyValue<T> createLazyValue(@NotNull Computable<T> computable);
@NotNull
<T> NotNullLazyValue<T> createRecursionTolerantLazyValue(@NotNull Computable<T> computable, @NotNull T onRecursiveCall);
/**
* {@code postCompute} is called after the value is computed, but before any other thread sees it (the current thread may
* @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
* @param postCompute is called after the value is computed, but before any other thread sees it (the current thread may
* see it in between)
*/
@NotNull
<T> NotNullLazyValue<T> createLazyValueWithPostCompute(@NotNull Computable<T> computable, @NotNull Consumer<T> postCompute);
<T> NotNullLazyValue<T> createLazyValueWithPostCompute(
@NotNull Computable<T> computable,
@Nullable Computable<Object> onRecursiveCall,
@NotNull Consumer<T> postCompute
);
@NotNull
<T> NullableLazyValue<T> createNullableLazyValue(@NotNull Computable<T> computable);
/**
* If recursion is detected, respective calls to compute() simply return null
*/
@NotNull
<T> NullableLazyValue<T> createRecursionTolerantNullableLazyValue(@NotNull Computable<T> computable);
<T> NullableLazyValue<T> createRecursionTolerantNullableLazyValue(@NotNull Computable<T> computable, @Nullable T onRecursiveCall);
/**
* {@code postCompute} is called after the value is computed, but before any other thread sees it (the current thread may