[LL FIR] try to check for PCE in ValueWithPostCompute to avoid possible deadlocks
This commit is contained in:
committed by
Space Team
parent
de7383ff15
commit
f9298d8e85
+9
-4
@@ -5,7 +5,9 @@
|
||||
|
||||
package org.jetbrains.kotlin.analysis.low.level.api.fir.fir.caches
|
||||
|
||||
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.lockWithPCECheck
|
||||
import org.jetbrains.kotlin.util.shouldIjPlatformExceptionBeRethrown
|
||||
import java.util.concurrent.locks.ReentrantLock
|
||||
|
||||
/**
|
||||
* Lazily calculated value which runs postCompute in the same thread,
|
||||
@@ -24,6 +26,7 @@ internal class ValueWithPostCompute<KEY, VALUE, DATA>(
|
||||
) {
|
||||
private var _calculate: ((KEY) -> Pair<VALUE, DATA>)? = calculate
|
||||
private var _postCompute: ((KEY, VALUE, DATA) -> Unit)? = postCompute
|
||||
private val lock = ReentrantLock()
|
||||
|
||||
/**
|
||||
* can be in one of the following three states:
|
||||
@@ -58,7 +61,7 @@ internal class ValueWithPostCompute<KEY, VALUE, DATA>(
|
||||
if (stateSnapshot.threadId == Thread.currentThread().id) {
|
||||
return stateSnapshot.value as VALUE
|
||||
} else {
|
||||
synchronized(this) { // wait until other thread which holds the lock now computes the value
|
||||
lock.lockWithPCECheck(LOCKING_INTERVAL_MS) { // wait until other thread which holds the lock now computes the value
|
||||
when (val newStateSnapshot = value) {
|
||||
ValueIsNotComputed -> {
|
||||
// if we have a PCE during value computation, then we will enter the critical section with `value == ValueIsNotComputed`
|
||||
@@ -77,7 +80,7 @@ internal class ValueWithPostCompute<KEY, VALUE, DATA>(
|
||||
}
|
||||
}
|
||||
}
|
||||
ValueIsNotComputed -> synchronized(this) {
|
||||
ValueIsNotComputed -> lock.lockWithPCECheck(LOCKING_INTERVAL_MS) {
|
||||
return computeValueWithoutLock()
|
||||
}
|
||||
is ExceptionWasThrownDuringValueComputation -> {
|
||||
@@ -92,7 +95,7 @@ internal class ValueWithPostCompute<KEY, VALUE, DATA>(
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
// should be called under a synchronized section
|
||||
private fun computeValueWithoutLock(): VALUE {
|
||||
require(Thread.holdsLock(this))
|
||||
require(lock.isHeldByCurrentThread)
|
||||
// if we entered synchronized section that's mean that the value is not yet calculated and was not started to be calculated
|
||||
// or the some other thread calculated the value while we were waiting to acquire the lock
|
||||
|
||||
@@ -146,4 +149,6 @@ internal class ValueWithPostCompute<KEY, VALUE, DATA>(
|
||||
private class ValueIsPostComputingNow(val value: Any?, val threadId: Long)
|
||||
private class ExceptionWasThrownDuringValueComputation(val error: Throwable)
|
||||
private object ValueIsNotComputed
|
||||
}
|
||||
}
|
||||
|
||||
private const val LOCKING_INTERVAL_MS = 50L
|
||||
Reference in New Issue
Block a user