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 package org.jetbrains.kotlin.context
import com.intellij.openapi.progress.ProcessCanceledException
import com.intellij.openapi.progress.ProgressManager import com.intellij.openapi.progress.ProgressManager
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
@@ -86,9 +87,9 @@ class MutableModuleContextImpl(
fun GlobalContext(debugName: String): GlobalContextImpl { fun GlobalContext(debugName: String): GlobalContextImpl {
val tracker = ExceptionTracker() val tracker = ExceptionTracker()
return GlobalContextImpl(LockBasedStorageManager.createWithExceptionHandling(debugName, tracker) { return GlobalContextImpl(LockBasedStorageManager.createWithExceptionHandling(debugName, tracker, {
ProgressManager.checkCanceled() ProgressManager.checkCanceled()
}, tracker) }, { throw ProcessCanceledException(it) }), tracker)
} }
fun ProjectContext(project: Project, debugName: String): ProjectContext = ProjectContextImpl(project, GlobalContext(debugName)) fun ProjectContext(project: Project, debugName: String): ProjectContext = ProjectContextImpl(project, GlobalContext(debugName))
@@ -66,17 +66,18 @@ public class LockBasedStorageManager implements StorageManager {
@NotNull String debugText, @NotNull String debugText,
@NotNull ExceptionHandlingStrategy exceptionHandlingStrategy @NotNull ExceptionHandlingStrategy exceptionHandlingStrategy
) { ) {
return createWithExceptionHandling(debugText, exceptionHandlingStrategy, null); return createWithExceptionHandling(debugText, exceptionHandlingStrategy, null, null);
} }
@NotNull @NotNull
public static LockBasedStorageManager createWithExceptionHandling( public static LockBasedStorageManager createWithExceptionHandling(
@NotNull String debugText, @NotNull String debugText,
@NotNull ExceptionHandlingStrategy exceptionHandlingStrategy, @NotNull ExceptionHandlingStrategy exceptionHandlingStrategy,
@Nullable Runnable checkCancelled @Nullable Runnable checkCancelled,
@Nullable Function1<InterruptedException, Unit> interruptedExceptionHandler
) { ) {
return new LockBasedStorageManager(debugText, exceptionHandlingStrategy, return new LockBasedStorageManager(debugText, exceptionHandlingStrategy,
SimpleLock.Companion.simpleLock(checkCancelled)); SimpleLock.Companion.simpleLock(checkCancelled, interruptedExceptionHandler));
} }
protected final SimpleLock lock; protected final SimpleLock lock;
@@ -94,11 +95,15 @@ public class LockBasedStorageManager implements StorageManager {
} }
public LockBasedStorageManager(String debugText) { public LockBasedStorageManager(String debugText) {
this(debugText, null); this(debugText, (Runnable)null, (Function1)null);
} }
public LockBasedStorageManager(String debugText, @Nullable Runnable checkCancelled) { public LockBasedStorageManager(
this(debugText, ExceptionHandlingStrategy.THROW, SimpleLock.Companion.simpleLock(checkCancelled)); String debugText,
@Nullable Runnable checkCancelled,
@Nullable Function1<InterruptedException, Unit> interruptedExceptionHandler
) {
this(debugText, ExceptionHandlingStrategy.THROW, SimpleLock.Companion.simpleLock(checkCancelled, interruptedExceptionHandler));
} }
@Override @Override
@@ -17,8 +17,12 @@ interface SimpleLock {
fun unlock() fun unlock()
companion object { companion object {
fun simpleLock(checkCancelled: Runnable? = null) = fun simpleLock(checkCancelled: Runnable? = null, interruptedExceptionHandler: ((InterruptedException) -> Unit)? = null) =
checkCancelled?.let { CancellableSimpleLock(it) } ?: DefaultSimpleLock() 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) { class CancellableSimpleLock(
constructor(checkCancelled: Runnable) : this(checkCancelled = checkCancelled, lock = ReentrantLock()) 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() { override fun lock() {
while (!lock.tryLock(CHECK_CANCELLATION_PERIOD_MS, TimeUnit.MILLISECONDS)) { try {
//ProgressIndicatorAndCompilationCanceledStatus.checkCanceled() while (!lock.tryLock(CHECK_CANCELLATION_PERIOD_MS, TimeUnit.MILLISECONDS)) {
checkCancelled.run() //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 val cache = HashMap<PsiElement, AnalysisResult>()
private var fileResult: AnalysisResult? = null private var fileResult: AnalysisResult? = null
private val lock = ReentrantLock() private val lock = ReentrantLock()
private val guardLock = CancellableSimpleLock(lock) { private val guardLock = CancellableSimpleLock(lock,
ProgressIndicatorProvider.checkCanceled() checkCancelled = {
} ProgressIndicatorProvider.checkCanceled()
},
interruptedExceptionHandler = { throw ProcessCanceledException(it) })
private fun check(element: KtElement) { private fun check(element: KtElement) {
checkWithAttachment(element.containingFile == file, { checkWithAttachment(element.containingFile == file, {
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.idea.caches.resolve package org.jetbrains.kotlin.idea.caches.resolve
import com.intellij.openapi.progress.ProcessCanceledException
import com.intellij.openapi.progress.ProgressManager import com.intellij.openapi.progress.ProgressManager
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
@@ -51,9 +52,11 @@ internal class ProjectResolutionFacade(
get() = globalContext.storageManager.compute { cachedValue.value } get() = globalContext.storageManager.compute { cachedValue.value }
private val analysisResultsLock = ReentrantLock() private val analysisResultsLock = ReentrantLock()
private val analysisResultsSimpleLock = CancellableSimpleLock(analysisResultsLock) { private val analysisResultsSimpleLock = CancellableSimpleLock(analysisResultsLock,
ProgressManager.checkCanceled() checkCancelled = {
} ProgressManager.checkCanceled()
},
interruptedExceptionHandler = { throw ProcessCanceledException(it) })
private val analysisResults = CachedValuesManager.getManager(project).createCachedValue( private val analysisResults = CachedValuesManager.getManager(project).createCachedValue(
{ {
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.idea.caches.resolve.util package org.jetbrains.kotlin.idea.caches.resolve.util
import com.intellij.openapi.progress.ProcessCanceledException
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.context.GlobalContextImpl import org.jetbrains.kotlin.context.GlobalContextImpl
import org.jetbrains.kotlin.idea.project.libraryToSourceAnalysisEnabled import org.jetbrains.kotlin.idea.project.libraryToSourceAnalysisEnabled
@@ -24,9 +25,9 @@ private fun GlobalContextImpl.contextWithCompositeExceptionTracker(debugName: St
private fun GlobalContextImpl.contextWithNewLockAndCompositeExceptionTracker(debugName: String): GlobalContextImpl { private fun GlobalContextImpl.contextWithNewLockAndCompositeExceptionTracker(debugName: String): GlobalContextImpl {
val newExceptionTracker = CompositeExceptionTracker(this.exceptionTracker) val newExceptionTracker = CompositeExceptionTracker(this.exceptionTracker)
return GlobalContextImpl( return GlobalContextImpl(
LockBasedStorageManager.createWithExceptionHandling(debugName, newExceptionTracker) { LockBasedStorageManager.createWithExceptionHandling(debugName, newExceptionTracker, {
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled() ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
}, }, { throw ProcessCanceledException(it) }),
newExceptionTracker newExceptionTracker
) )
} }
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.scripting.resolve package org.jetbrains.kotlin.scripting.resolve
import com.intellij.openapi.progress.ProcessCanceledException
import com.intellij.openapi.progress.ProgressManager import com.intellij.openapi.progress.ProgressManager
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.builtins.DefaultBuiltIns 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 { internal fun constructAnnotation(psi: KtAnnotationEntry, targetClass: KClass<out Annotation>, project: Project): Annotation {
val module = ModuleDescriptorImpl( val module = ModuleDescriptorImpl(
Name.special("<script-annotations-preprocessing>"), Name.special("<script-annotations-preprocessing>"),
LockBasedStorageManager("scriptAnnotationsPreprocessing") { LockBasedStorageManager("scriptAnnotationsPreprocessing", {
ProgressManager.checkCanceled() ProgressManager.checkCanceled()
}, }, { throw ProcessCanceledException(it) }),
DefaultBuiltIns.Instance DefaultBuiltIns.Instance
) )
val evaluator = ConstantExpressionEvaluator(module, LanguageVersionSettingsImpl.DEFAULT, project) val evaluator = ConstantExpressionEvaluator(module, LanguageVersionSettingsImpl.DEFAULT, project)