From 961429831c546808d7e60cabc92286bc7662625a Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Fri, 8 Feb 2013 16:19:31 +0400 Subject: [PATCH] StorageManager can create thread-safe memoized functions --- .../resolve/lazy/LockBasedStorageManager.java | 33 +++++++++++++++++++ .../jet/lang/resolve/lazy/StorageManager.java | 14 ++++++++ 2 files changed, 47 insertions(+) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/LockBasedStorageManager.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/LockBasedStorageManager.java index 393af7e09fb..19f58da2b1f 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/LockBasedStorageManager.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/LockBasedStorageManager.java @@ -17,6 +17,8 @@ package org.jetbrains.jet.lang.resolve.lazy; import com.intellij.openapi.util.Computable; +import com.intellij.util.Function; +import com.intellij.util.containers.ConcurrentWeakValueHashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.diagnostics.Diagnostic; @@ -30,6 +32,8 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentMap; +import static org.jetbrains.jet.lang.resolve.lazy.StorageManager.MemoizationMode.WEAK; + public class LockBasedStorageManager implements StorageManager { private final Object lock = new Object() { @@ -45,6 +49,35 @@ public class LockBasedStorageManager implements StorageManager { return new ConcurrentHashMap(); } + @NotNull + @Override + public Function createMemoizedFunction(@NotNull final Function compute, @NotNull final MemoizationMode mode) { + return new Function() { + private final ConcurrentMap> cache; + { + cache = (mode == WEAK) ? new ConcurrentWeakValueHashMap>() : new ConcurrentHashMap>(); + } + + @Override + public V fun(@NotNull final K input) { + LazyValue lazyValue = cache.get(input); + if (lazyValue != null) return lazyValue.get(); + + lazyValue = createLazyValue(new Computable() { + @Override + public V compute() { + return compute.fun(input); + } + }); + + LazyValue oldValue = cache.putIfAbsent(input, lazyValue); + if (oldValue != null) return oldValue.get(); + + return lazyValue.get(); + } + }; + } + @Override public Collection createConcurrentCollection() { return new ConcurrentLinkedQueue(); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/StorageManager.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/StorageManager.java index 65d37686268..d1ebb20dedd 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/StorageManager.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/lazy/StorageManager.java @@ -17,6 +17,7 @@ package org.jetbrains.jet.lang.resolve.lazy; import com.intellij.openapi.util.Computable; +import com.intellij.util.Function; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.resolve.BindingTrace; @@ -27,6 +28,14 @@ public interface StorageManager { @NotNull ConcurrentMap createConcurrentMap(); + /** + * Given a function compute: K -> V create a memoized version of it that computes a value only once for each key + * @param compute the function to be memoized + * @param modeForValues how to store teh memoized values + */ + @NotNull + Function createMemoizedFunction(@NotNull Function compute, @NotNull MemoizationMode modeForValues); + Collection createConcurrentCollection(); @NotNull @@ -34,4 +43,9 @@ public interface StorageManager { @NotNull BindingTrace createSafeTrace(@NotNull BindingTrace originalTrace); + + enum MemoizationMode { + STRONG, + WEAK + } }