[LL FIR] restructure lock assertion to prevent NPEs
When the other thread has already computed the value and cleared the lock, the other thread could still enter the computeValueWithoutLock() and see lock == null
This commit is contained in:
committed by
Space Team
parent
11bc3dbd82
commit
879f6c3432
+6
-3
@@ -96,20 +96,22 @@ internal class ValueWithPostCompute<KEY, VALUE, DATA>(
|
|||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
// should be called under a synchronized section
|
// should be called under a synchronized section
|
||||||
private fun computeValueWithoutLock(): VALUE {
|
private fun computeValueWithoutLock(): VALUE {
|
||||||
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
|
// 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
|
// or the some other thread calculated the value while we were waiting to acquire the lock
|
||||||
|
|
||||||
when (val newStateSnapshot = value) {
|
when (val newStateSnapshot = value) {
|
||||||
ValueIsNotComputed -> {
|
ValueIsNotComputed -> {
|
||||||
// will be computed next
|
// will be computed later, the read of `ValueIsNotComputed` guarantees that lock is not null
|
||||||
|
require(lock!!.isHeldByCurrentThread)
|
||||||
}
|
}
|
||||||
is ExceptionWasThrownDuringValueComputation -> {
|
is ExceptionWasThrownDuringValueComputation -> {
|
||||||
// if some other thread tried to compute the value but failed with the exception
|
// if some other thread tried to compute the value but failed with the exception
|
||||||
throw newStateSnapshot.error
|
throw newStateSnapshot.error
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
// other thread computed the value for us
|
// other thread computed the value for us and set `lock` to null
|
||||||
|
require(lock == null)
|
||||||
|
|
||||||
return value as VALUE
|
return value as VALUE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -134,6 +136,7 @@ internal class ValueWithPostCompute<KEY, VALUE, DATA>(
|
|||||||
lock = null
|
lock = null
|
||||||
guard = null
|
guard = null
|
||||||
value = calculatedValue
|
value = calculatedValue
|
||||||
|
|
||||||
return calculatedValue
|
return calculatedValue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user