Protecting the trace with a lock

This commit is contained in:
Andrey Breslav
2013-01-28 22:27:44 +04:00
parent c2822fdad7
commit 5eb173e8dd
3 changed files with 73 additions and 1 deletions
@@ -19,7 +19,13 @@ package org.jetbrains.jet.lang.resolve.lazy;
import com.intellij.openapi.util.Computable;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.util.slicedmap.ReadOnlySlice;
import org.jetbrains.jet.util.slicedmap.WritableSlice;
import java.util.Collection;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@@ -44,6 +50,14 @@ public class LockBasedStorageManager implements StorageManager {
return new LockBasedLazyValue<T>(lock, computable);
}
@NotNull
@Override
public BindingTrace createSafeTrace(@NotNull BindingTrace originalTrace) {
// It seems safe to have a separate lock for traces:
// no other locks will be acquired inside the trace operations
return new LockProtectedTrace(lock, originalTrace);
}
private static class LockBasedLazyValue<T> implements LazyValue<T> {
private final Object lock;
private final Computable<T> computable;
@@ -74,4 +88,58 @@ public class LockBasedStorageManager implements StorageManager {
}
}
}
private static class LockProtectedTrace implements BindingTrace {
private final Object lock;
private final BindingTrace trace;
public LockProtectedTrace(@NotNull Object lock, @NotNull BindingTrace trace) {
this.lock = lock;
this.trace = trace;
}
@Override
public BindingContext getBindingContext() {
synchronized (lock) {
return trace.getBindingContext();
}
}
@Override
public <K, V> void record(WritableSlice<K, V> slice, K key, V value) {
synchronized (lock) {
trace.record(slice, key, value);
}
}
@Override
public <K> void record(WritableSlice<K, Boolean> slice, K key) {
synchronized (lock) {
trace.record(slice, key);
}
}
@Override
@Nullable
public <K, V> V get(ReadOnlySlice<K, V> slice, K key) {
synchronized (lock) {
return trace.get(slice, key);
}
}
@Override
@NotNull
public <K, V> Collection<K> getKeys(WritableSlice<K, V> slice) {
synchronized (lock) {
return trace.getKeys(slice);
}
}
@Override
public void report(@NotNull Diagnostic diagnostic) {
synchronized (lock) {
trace.report(diagnostic);
}
}
}
}
@@ -107,7 +107,7 @@ public class ResolveSession {
this.storageManager = storageManager;
this.classifierAliases = classifierAliases;
this.specialClasses = specialClasses;
this.trace = new ObservableBindingTrace(delegationTrace);
this.trace = storageManager.createSafeTrace(delegationTrace);
this.injector = new InjectorForLazyResolve(project, this, trace, moduleConfiguration);
this.module = rootDescriptor;
this.moduleConfiguration = moduleConfiguration;
@@ -18,6 +18,7 @@ package org.jetbrains.jet.lang.resolve.lazy;
import com.intellij.openapi.util.Computable;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import java.util.concurrent.ConcurrentMap;
@@ -27,4 +28,7 @@ public interface StorageManager {
@NotNull
<T> LazyValue<T> createLazyValue(@NotNull Computable<T> computable);
@NotNull
BindingTrace createSafeTrace(@NotNull BindingTrace originalTrace);
}