Use ReentrantLock instead of intrinsic locks in LockBasedStorageManager
This commit is contained in:
+50
-13
@@ -29,6 +29,7 @@ import org.jetbrains.jet.util.slicedmap.ReadOnlySlice;
|
|||||||
import org.jetbrains.jet.util.slicedmap.WritableSlice;
|
import org.jetbrains.jet.util.slicedmap.WritableSlice;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.concurrent.locks.Lock;
|
||||||
|
|
||||||
public class LockBasedLazyResolveStorageManager extends LockBasedStorageManager implements LazyResolveStorageManager {
|
public class LockBasedLazyResolveStorageManager extends LockBasedStorageManager implements LazyResolveStorageManager {
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -40,10 +41,10 @@ public class LockBasedLazyResolveStorageManager extends LockBasedStorageManager
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static class LockProtectedContext implements BindingContext {
|
private static class LockProtectedContext implements BindingContext {
|
||||||
private final Object lock;
|
private final Lock lock;
|
||||||
private final BindingContext context;
|
private final BindingContext context;
|
||||||
|
|
||||||
private LockProtectedContext(Object lock, BindingContext context) {
|
private LockProtectedContext(Lock lock, BindingContext context) {
|
||||||
this.lock = lock;
|
this.lock = lock;
|
||||||
this.context = context;
|
this.context = context;
|
||||||
}
|
}
|
||||||
@@ -51,43 +52,59 @@ public class LockBasedLazyResolveStorageManager extends LockBasedStorageManager
|
|||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public Diagnostics getDiagnostics() {
|
public Diagnostics getDiagnostics() {
|
||||||
synchronized (lock) {
|
lock.lock();
|
||||||
|
try {
|
||||||
return context.getDiagnostics();
|
return context.getDiagnostics();
|
||||||
}
|
}
|
||||||
|
finally {
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public <K, V> V get(ReadOnlySlice<K, V> slice, K key) {
|
public <K, V> V get(ReadOnlySlice<K, V> slice, K key) {
|
||||||
synchronized (lock) {
|
lock.lock();
|
||||||
|
try {
|
||||||
return context.get(slice, key);
|
return context.get(slice, key);
|
||||||
}
|
}
|
||||||
|
finally {
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public <K, V> Collection<K> getKeys(WritableSlice<K, V> slice) {
|
public <K, V> Collection<K> getKeys(WritableSlice<K, V> slice) {
|
||||||
synchronized (lock) {
|
lock.lock();
|
||||||
|
try {
|
||||||
return context.getKeys(slice);
|
return context.getKeys(slice);
|
||||||
}
|
}
|
||||||
|
finally {
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
@TestOnly
|
@TestOnly
|
||||||
public <K, V> ImmutableMap<K, V> getSliceContents(@NotNull ReadOnlySlice<K, V> slice) {
|
public <K, V> ImmutableMap<K, V> getSliceContents(@NotNull ReadOnlySlice<K, V> slice) {
|
||||||
synchronized (lock) {
|
lock.lock();
|
||||||
|
try {
|
||||||
return context.getSliceContents(slice);
|
return context.getSliceContents(slice);
|
||||||
}
|
}
|
||||||
|
finally {
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class LockProtectedTrace implements BindingTrace {
|
private static class LockProtectedTrace implements BindingTrace {
|
||||||
private final Object lock;
|
private final Lock lock;
|
||||||
private final BindingTrace trace;
|
private final BindingTrace trace;
|
||||||
private final BindingContext context;
|
private final BindingContext context;
|
||||||
|
|
||||||
public LockProtectedTrace(@NotNull Object lock, @NotNull BindingTrace trace) {
|
public LockProtectedTrace(@NotNull Lock lock, @NotNull BindingTrace trace) {
|
||||||
this.lock = lock;
|
this.lock = lock;
|
||||||
this.trace = trace;
|
this.trace = trace;
|
||||||
this.context = new LockProtectedContext(lock, trace.getBindingContext());
|
this.context = new LockProtectedContext(lock, trace.getBindingContext());
|
||||||
@@ -100,39 +117,59 @@ public class LockBasedLazyResolveStorageManager extends LockBasedStorageManager
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <K, V> void record(WritableSlice<K, V> slice, K key, V value) {
|
public <K, V> void record(WritableSlice<K, V> slice, K key, V value) {
|
||||||
synchronized (lock) {
|
lock.lock();
|
||||||
|
try {
|
||||||
trace.record(slice, key, value);
|
trace.record(slice, key, value);
|
||||||
}
|
}
|
||||||
|
finally {
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <K> void record(WritableSlice<K, Boolean> slice, K key) {
|
public <K> void record(WritableSlice<K, Boolean> slice, K key) {
|
||||||
synchronized (lock) {
|
lock.lock();
|
||||||
|
try {
|
||||||
trace.record(slice, key);
|
trace.record(slice, key);
|
||||||
}
|
}
|
||||||
|
finally {
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Nullable
|
@Nullable
|
||||||
public <K, V> V get(ReadOnlySlice<K, V> slice, K key) {
|
public <K, V> V get(ReadOnlySlice<K, V> slice, K key) {
|
||||||
synchronized (lock) {
|
lock.lock();
|
||||||
|
try {
|
||||||
return trace.get(slice, key);
|
return trace.get(slice, key);
|
||||||
}
|
}
|
||||||
|
finally {
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NotNull
|
@NotNull
|
||||||
public <K, V> Collection<K> getKeys(WritableSlice<K, V> slice) {
|
public <K, V> Collection<K> getKeys(WritableSlice<K, V> slice) {
|
||||||
synchronized (lock) {
|
lock.lock();
|
||||||
|
try {
|
||||||
return trace.getKeys(slice);
|
return trace.getKeys(slice);
|
||||||
}
|
}
|
||||||
|
finally {
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void report(@NotNull Diagnostic diagnostic) {
|
public void report(@NotNull Diagnostic diagnostic) {
|
||||||
synchronized (lock) {
|
lock.lock();
|
||||||
|
try {
|
||||||
trace.report(diagnostic);
|
trace.report(diagnostic);
|
||||||
}
|
}
|
||||||
|
finally {
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,15 +27,12 @@ import org.jetbrains.jet.utils.WrappedValues;
|
|||||||
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
import java.util.concurrent.locks.Lock;
|
||||||
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
|
||||||
public class LockBasedStorageManager implements StorageManager {
|
public class LockBasedStorageManager implements StorageManager {
|
||||||
|
|
||||||
protected final Object lock = new Object() {
|
protected final Lock lock = new ReentrantLock();
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "LockBasedStorageManager centralized lock";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
@@ -134,9 +131,13 @@ public class LockBasedStorageManager implements StorageManager {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> T compute(@NotNull Computable<T> computable) {
|
public <T> T compute(@NotNull Computable<T> computable) {
|
||||||
synchronized (lock) {
|
lock.lock();
|
||||||
|
try {
|
||||||
return computable.compute();
|
return computable.compute();
|
||||||
}
|
}
|
||||||
|
finally {
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class LockBasedLazyValue<T> implements NullableLazyValue<T> {
|
private static class LockBasedLazyValue<T> implements NullableLazyValue<T> {
|
||||||
@@ -144,13 +145,13 @@ public class LockBasedStorageManager implements StorageManager {
|
|||||||
private static final Object NOT_COMPUTED = new Object();
|
private static final Object NOT_COMPUTED = new Object();
|
||||||
private static final Object COMPUTING = new Object();
|
private static final Object COMPUTING = new Object();
|
||||||
|
|
||||||
private final Object lock;
|
private final Lock lock;
|
||||||
private final Computable<T> computable;
|
private final Computable<T> computable;
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private volatile Object value = NOT_COMPUTED;
|
private volatile Object value = NOT_COMPUTED;
|
||||||
|
|
||||||
public LockBasedLazyValue(@NotNull Object lock, @NotNull Computable<T> computable) {
|
public LockBasedLazyValue(@NotNull Lock lock, @NotNull Computable<T> computable) {
|
||||||
this.lock = lock;
|
this.lock = lock;
|
||||||
this.computable = computable;
|
this.computable = computable;
|
||||||
}
|
}
|
||||||
@@ -165,7 +166,8 @@ public class LockBasedStorageManager implements StorageManager {
|
|||||||
Object _value = value;
|
Object _value = value;
|
||||||
if (_value != NOT_COMPUTED && _value != COMPUTING) return WrappedValues.unescapeThrowable(_value);
|
if (_value != NOT_COMPUTED && _value != COMPUTING) return WrappedValues.unescapeThrowable(_value);
|
||||||
|
|
||||||
synchronized (lock) {
|
lock.lock();
|
||||||
|
try {
|
||||||
_value = value;
|
_value = value;
|
||||||
if (_value == COMPUTING) {
|
if (_value == COMPUTING) {
|
||||||
Object result = recursionDetected();
|
Object result = recursionDetected();
|
||||||
@@ -188,6 +190,9 @@ public class LockBasedStorageManager implements StorageManager {
|
|||||||
throw ExceptionUtils.rethrow(throwable);
|
throw ExceptionUtils.rethrow(throwable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
finally {
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -206,7 +211,7 @@ public class LockBasedStorageManager implements StorageManager {
|
|||||||
|
|
||||||
private static class LockBasedNotNullLazyValue<T> extends LockBasedLazyValue<T> implements NotNullLazyValue<T> {
|
private static class LockBasedNotNullLazyValue<T> extends LockBasedLazyValue<T> implements NotNullLazyValue<T> {
|
||||||
|
|
||||||
public LockBasedNotNullLazyValue(@NotNull Object lock, @NotNull Computable<T> computable) {
|
public LockBasedNotNullLazyValue(@NotNull Lock lock, @NotNull Computable<T> computable) {
|
||||||
super(lock, computable);
|
super(lock, computable);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -220,11 +225,11 @@ public class LockBasedStorageManager implements StorageManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static class MapBasedMemoizedFunction<K, V> implements MemoizedFunctionToNullable<K, V> {
|
private static class MapBasedMemoizedFunction<K, V> implements MemoizedFunctionToNullable<K, V> {
|
||||||
private final Object lock;
|
private final Lock lock;
|
||||||
private final ConcurrentMap<K, Object> cache;
|
private final ConcurrentMap<K, Object> cache;
|
||||||
private final Function<K, V> compute;
|
private final Function<K, V> compute;
|
||||||
|
|
||||||
public MapBasedMemoizedFunction(@NotNull Object lock, @NotNull ConcurrentMap<K, Object> map, @NotNull Function<K, V> compute) {
|
public MapBasedMemoizedFunction(@NotNull Lock lock, @NotNull ConcurrentMap<K, Object> map, @NotNull Function<K, V> compute) {
|
||||||
this.lock = lock;
|
this.lock = lock;
|
||||||
this.cache = map;
|
this.cache = map;
|
||||||
this.compute = compute;
|
this.compute = compute;
|
||||||
@@ -236,7 +241,8 @@ public class LockBasedStorageManager implements StorageManager {
|
|||||||
Object value = cache.get(input);
|
Object value = cache.get(input);
|
||||||
if (value != null) return WrappedValues.unescapeExceptionOrNull(value);
|
if (value != null) return WrappedValues.unescapeExceptionOrNull(value);
|
||||||
|
|
||||||
synchronized (lock) {
|
lock.lock();
|
||||||
|
try {
|
||||||
value = cache.get(input);
|
value = cache.get(input);
|
||||||
if (value != null) return WrappedValues.unescapeExceptionOrNull(value);
|
if (value != null) return WrappedValues.unescapeExceptionOrNull(value);
|
||||||
|
|
||||||
@@ -254,13 +260,16 @@ public class LockBasedStorageManager implements StorageManager {
|
|||||||
throw ExceptionUtils.rethrow(throwable);
|
throw ExceptionUtils.rethrow(throwable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
finally {
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class MapBasedMemoizedFunctionToNotNull<K, V> extends MapBasedMemoizedFunction<K, V> implements MemoizedFunctionToNotNull<K, V> {
|
private static class MapBasedMemoizedFunctionToNotNull<K, V> extends MapBasedMemoizedFunction<K, V> implements MemoizedFunctionToNotNull<K, V> {
|
||||||
|
|
||||||
public MapBasedMemoizedFunctionToNotNull(
|
public MapBasedMemoizedFunctionToNotNull(
|
||||||
@NotNull Object lock,
|
@NotNull Lock lock,
|
||||||
@NotNull ConcurrentMap<K, Object> map,
|
@NotNull ConcurrentMap<K, Object> map,
|
||||||
@NotNull Function<K, V> compute
|
@NotNull Function<K, V> compute
|
||||||
) {
|
) {
|
||||||
|
|||||||
Reference in New Issue
Block a user