Perform tryLock-and-checkCanceled on waiting lock in LockBasedStorageManager

Relates to #KT-38012
This commit is contained in:
Vladimir Dolzhenko
2020-04-09 16:23:24 +02:00
parent 6fae29bcc0
commit b0483a67c2
7 changed files with 117 additions and 27 deletions
@@ -29,8 +29,6 @@ import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class LockBasedStorageManager implements StorageManager {
private static final String PACKAGE_NAME = StringsKt.substringBeforeLast(LockBasedStorageManager.class.getCanonicalName(), ".", "");
@@ -55,7 +53,7 @@ public class LockBasedStorageManager implements StorageManager {
RuntimeException handleException(@NotNull Throwable throwable);
}
public static final StorageManager NO_LOCKS = new LockBasedStorageManager("NO_LOCKS", ExceptionHandlingStrategy.THROW, NoLock.INSTANCE) {
public static final StorageManager NO_LOCKS = new LockBasedStorageManager("NO_LOCKS", ExceptionHandlingStrategy.THROW, EmptySimpleLock.INSTANCE) {
@NotNull
@Override
protected <T> RecursionDetectedResult<T> recursionDetectedDefault() {
@@ -64,18 +62,31 @@ public class LockBasedStorageManager implements StorageManager {
};
@NotNull
public static LockBasedStorageManager createWithExceptionHandling(@NotNull String debugText, @NotNull ExceptionHandlingStrategy exceptionHandlingStrategy) {
return new LockBasedStorageManager(debugText, exceptionHandlingStrategy, new ReentrantLock());
public static LockBasedStorageManager createWithExceptionHandling(
@NotNull String debugText,
@NotNull ExceptionHandlingStrategy exceptionHandlingStrategy
) {
return createWithExceptionHandling(debugText, exceptionHandlingStrategy, null);
}
protected final Lock lock;
@NotNull
public static LockBasedStorageManager createWithExceptionHandling(
@NotNull String debugText,
@NotNull ExceptionHandlingStrategy exceptionHandlingStrategy,
@Nullable Runnable checkCancelled
) {
return new LockBasedStorageManager(debugText, exceptionHandlingStrategy,
SimpleLock.Companion.simpleLock(checkCancelled));
}
protected final SimpleLock lock;
private final ExceptionHandlingStrategy exceptionHandlingStrategy;
private final String debugText;
private LockBasedStorageManager(
@NotNull String debugText,
@NotNull ExceptionHandlingStrategy exceptionHandlingStrategy,
@NotNull Lock lock
@NotNull SimpleLock lock
) {
this.lock = lock;
this.exceptionHandlingStrategy = exceptionHandlingStrategy;
@@ -83,7 +94,11 @@ public class LockBasedStorageManager implements StorageManager {
}
public LockBasedStorageManager(String debugText) {
this(debugText, ExceptionHandlingStrategy.THROW, new ReentrantLock());
this(debugText, null);
}
public LockBasedStorageManager(String debugText, @Nullable Runnable checkCancelled) {
this(debugText, ExceptionHandlingStrategy.THROW, SimpleLock.Companion.simpleLock(checkCancelled));
}
@Override
@@ -0,0 +1,60 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.storage
import java.util.concurrent.TimeUnit
import java.util.concurrent.locks.Lock
import java.util.concurrent.locks.ReentrantLock
private const val CHECK_CANCELLATION_PERIOD_MS: Long = 50
interface SimpleLock {
fun lock()
fun unlock()
companion object {
fun simpleLock(checkCancelled: Runnable? = null) =
checkCancelled?.let { CancellableSimpleLock(it) } ?: DefaultSimpleLock()
}
}
inline fun <T> SimpleLock.guarded(crossinline computable: () -> T): T {
lock()
return try {
computable()
} finally {
unlock()
}
}
object EmptySimpleLock : SimpleLock {
override fun lock() {
}
override fun unlock() {
}
}
open class DefaultSimpleLock(protected val lock: Lock = ReentrantLock()) : SimpleLock {
override fun lock() = lock.lock()
override fun unlock() = lock.unlock()
}
class CancellableSimpleLock(lock: Lock, private val checkCancelled: Runnable) : DefaultSimpleLock(lock) {
constructor(checkCancelled: Runnable) : this(checkCancelled = checkCancelled, lock = ReentrantLock())
override fun lock() {
while (!lock.tryLock(CHECK_CANCELLATION_PERIOD_MS, TimeUnit.MILLISECONDS)) {
//ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
checkCancelled.run()
}
}
}