Add InterruptedException handler to CancellableSimpleLock

#EA-220650 Fixed
This commit is contained in:
Vladimir Dolzhenko
2020-06-25 23:46:00 +02:00
committed by Vladimir Dolzhenko
parent a9444c386d
commit ab20b3e083
7 changed files with 54 additions and 25 deletions
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.context
import com.intellij.openapi.progress.ProcessCanceledException
import com.intellij.openapi.progress.ProgressManager
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
@@ -86,9 +87,9 @@ class MutableModuleContextImpl(
fun GlobalContext(debugName: String): GlobalContextImpl {
val tracker = ExceptionTracker()
return GlobalContextImpl(LockBasedStorageManager.createWithExceptionHandling(debugName, tracker) {
return GlobalContextImpl(LockBasedStorageManager.createWithExceptionHandling(debugName, tracker, {
ProgressManager.checkCanceled()
}, tracker)
}, { throw ProcessCanceledException(it) }), tracker)
}
fun ProjectContext(project: Project, debugName: String): ProjectContext = ProjectContextImpl(project, GlobalContext(debugName))
@@ -66,17 +66,18 @@ public class LockBasedStorageManager implements StorageManager {
@NotNull String debugText,
@NotNull ExceptionHandlingStrategy exceptionHandlingStrategy
) {
return createWithExceptionHandling(debugText, exceptionHandlingStrategy, null);
return createWithExceptionHandling(debugText, exceptionHandlingStrategy, null, null);
}
@NotNull
public static LockBasedStorageManager createWithExceptionHandling(
@NotNull String debugText,
@NotNull ExceptionHandlingStrategy exceptionHandlingStrategy,
@Nullable Runnable checkCancelled
@Nullable Runnable checkCancelled,
@Nullable Function1<InterruptedException, Unit> interruptedExceptionHandler
) {
return new LockBasedStorageManager(debugText, exceptionHandlingStrategy,
SimpleLock.Companion.simpleLock(checkCancelled));
SimpleLock.Companion.simpleLock(checkCancelled, interruptedExceptionHandler));
}
protected final SimpleLock lock;
@@ -94,11 +95,15 @@ public class LockBasedStorageManager implements StorageManager {
}
public LockBasedStorageManager(String debugText) {
this(debugText, null);
this(debugText, (Runnable)null, (Function1)null);
}
public LockBasedStorageManager(String debugText, @Nullable Runnable checkCancelled) {
this(debugText, ExceptionHandlingStrategy.THROW, SimpleLock.Companion.simpleLock(checkCancelled));
public LockBasedStorageManager(
String debugText,
@Nullable Runnable checkCancelled,
@Nullable Function1<InterruptedException, Unit> interruptedExceptionHandler
) {
this(debugText, ExceptionHandlingStrategy.THROW, SimpleLock.Companion.simpleLock(checkCancelled, interruptedExceptionHandler));
}
@Override
@@ -17,8 +17,12 @@ interface SimpleLock {
fun unlock()
companion object {
fun simpleLock(checkCancelled: Runnable? = null) =
checkCancelled?.let { CancellableSimpleLock(it) } ?: DefaultSimpleLock()
fun simpleLock(checkCancelled: Runnable? = null, interruptedExceptionHandler: ((InterruptedException) -> Unit)? = null) =
if (checkCancelled != null && interruptedExceptionHandler != null) {
CancellableSimpleLock(checkCancelled, interruptedExceptionHandler)
} else {
DefaultSimpleLock()
}
}
}
@@ -47,13 +51,25 @@ open class DefaultSimpleLock(protected val lock: Lock = ReentrantLock()) : Simpl
}
class CancellableSimpleLock(lock: Lock, private val checkCancelled: Runnable) : DefaultSimpleLock(lock) {
constructor(checkCancelled: Runnable) : this(checkCancelled = checkCancelled, lock = ReentrantLock())
class CancellableSimpleLock(
lock: Lock,
private val checkCancelled: Runnable,
private val interruptedExceptionHandler: (InterruptedException) -> Unit
) : DefaultSimpleLock(lock) {
constructor(checkCancelled: Runnable, interruptedExceptionHandler: (InterruptedException) -> Unit) : this(
checkCancelled = checkCancelled,
lock = ReentrantLock(),
interruptedExceptionHandler = interruptedExceptionHandler
)
override fun lock() {
while (!lock.tryLock(CHECK_CANCELLATION_PERIOD_MS, TimeUnit.MILLISECONDS)) {
//ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
checkCancelled.run()
try {
while (!lock.tryLock(CHECK_CANCELLATION_PERIOD_MS, TimeUnit.MILLISECONDS)) {
//ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
checkCancelled.run()
}
} catch (e: InterruptedException) {
interruptedExceptionHandler(e)
}
}
@@ -57,9 +57,11 @@ internal class PerFileAnalysisCache(val file: KtFile, componentProvider: Compone
private val cache = HashMap<PsiElement, AnalysisResult>()
private var fileResult: AnalysisResult? = null
private val lock = ReentrantLock()
private val guardLock = CancellableSimpleLock(lock) {
ProgressIndicatorProvider.checkCanceled()
}
private val guardLock = CancellableSimpleLock(lock,
checkCancelled = {
ProgressIndicatorProvider.checkCanceled()
},
interruptedExceptionHandler = { throw ProcessCanceledException(it) })
private fun check(element: KtElement) {
checkWithAttachment(element.containingFile == file, {
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.idea.caches.resolve
import com.intellij.openapi.progress.ProcessCanceledException
import com.intellij.openapi.progress.ProgressManager
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElement
@@ -51,9 +52,11 @@ internal class ProjectResolutionFacade(
get() = globalContext.storageManager.compute { cachedValue.value }
private val analysisResultsLock = ReentrantLock()
private val analysisResultsSimpleLock = CancellableSimpleLock(analysisResultsLock) {
ProgressManager.checkCanceled()
}
private val analysisResultsSimpleLock = CancellableSimpleLock(analysisResultsLock,
checkCancelled = {
ProgressManager.checkCanceled()
},
interruptedExceptionHandler = { throw ProcessCanceledException(it) })
private val analysisResults = CachedValuesManager.getManager(project).createCachedValue(
{
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.idea.caches.resolve.util
import com.intellij.openapi.progress.ProcessCanceledException
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.context.GlobalContextImpl
import org.jetbrains.kotlin.idea.project.libraryToSourceAnalysisEnabled
@@ -24,9 +25,9 @@ private fun GlobalContextImpl.contextWithCompositeExceptionTracker(debugName: St
private fun GlobalContextImpl.contextWithNewLockAndCompositeExceptionTracker(debugName: String): GlobalContextImpl {
val newExceptionTracker = CompositeExceptionTracker(this.exceptionTracker)
return GlobalContextImpl(
LockBasedStorageManager.createWithExceptionHandling(debugName, newExceptionTracker) {
LockBasedStorageManager.createWithExceptionHandling(debugName, newExceptionTracker, {
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
},
}, { throw ProcessCanceledException(it) }),
newExceptionTracker
)
}
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.scripting.resolve
import com.intellij.openapi.progress.ProcessCanceledException
import com.intellij.openapi.progress.ProgressManager
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
@@ -41,9 +42,9 @@ internal fun String?.orAnonymous(kind: String = ""): String =
internal fun constructAnnotation(psi: KtAnnotationEntry, targetClass: KClass<out Annotation>, project: Project): Annotation {
val module = ModuleDescriptorImpl(
Name.special("<script-annotations-preprocessing>"),
LockBasedStorageManager("scriptAnnotationsPreprocessing") {
LockBasedStorageManager("scriptAnnotationsPreprocessing", {
ProgressManager.checkCanceled()
},
}, { throw ProcessCanceledException(it) }),
DefaultBuiltIns.Instance
)
val evaluator = ConstantExpressionEvaluator(module, LanguageVersionSettingsImpl.DEFAULT, project)