[LL FIR] allow recursive access to the same FirThreadSafeCache
^KT-56721 fixed
This commit is contained in:
committed by
Space Team
parent
d670e5a695
commit
c60fd38e05
+1
-9
@@ -13,17 +13,9 @@ internal class FirThreadSafeCache<K : Any, V, CONTEXT>(
|
|||||||
private val createValue: (K, CONTEXT) -> V
|
private val createValue: (K, CONTEXT) -> V
|
||||||
) : FirCache<K, V, CONTEXT>() {
|
) : FirCache<K, V, CONTEXT>() {
|
||||||
|
|
||||||
private val updating: ThreadLocal<Boolean> = ThreadLocal.withInitial { false }
|
|
||||||
|
|
||||||
override fun getValue(key: K, context: CONTEXT): V =
|
override fun getValue(key: K, context: CONTEXT): V =
|
||||||
map.getOrPutWithNullableValue(key) {
|
map.getOrPutWithNullableValue(key) {
|
||||||
if (updating.get()) error("Recursive update")
|
createValue(it, context)
|
||||||
try {
|
|
||||||
updating.set(true)
|
|
||||||
createValue(it, context)
|
|
||||||
} finally {
|
|
||||||
updating.set(false)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getValueIfComputed(key: K): V? =
|
override fun getValueIfComputed(key: K): V? =
|
||||||
|
|||||||
+1
-1
@@ -19,6 +19,6 @@ internal inline fun <KEY : Any, RESULT> ConcurrentMap<KEY, Any>.getOrPutWithNull
|
|||||||
key: KEY,
|
key: KEY,
|
||||||
crossinline compute: (KEY) -> Any?
|
crossinline compute: (KEY) -> Any?
|
||||||
): RESULT {
|
): RESULT {
|
||||||
val value = computeIfAbsent(key) { compute(key) ?: NullValue }
|
val value = getOrPut(key) { compute(key) ?: NullValue }
|
||||||
return value.nullValueToNull()
|
return value.nullValueToNull()
|
||||||
}
|
}
|
||||||
+6
@@ -23,6 +23,12 @@ import kotlin.reflect.KClass
|
|||||||
* TODO:
|
* TODO:
|
||||||
* - check that annotations or meta-annotations is not empty
|
* - check that annotations or meta-annotations is not empty
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All `generate*` members have the contract that the computation should be side-effect-free.
|
||||||
|
* That means that all `generate*` function implementations should not modify any state or leak the generated `FirElement` or `FirBasedSymbol` (e.g., by putting it to some cache).
|
||||||
|
* This restriction is imposed by the corresponding IDE cache implementation, which might retry the computation several times.
|
||||||
|
*/
|
||||||
abstract class FirDeclarationGenerationExtension(session: FirSession) : FirExtension(session) {
|
abstract class FirDeclarationGenerationExtension(session: FirSession) : FirExtension(session) {
|
||||||
companion object {
|
companion object {
|
||||||
val NAME = FirExtensionPointName("ExistingClassModification")
|
val NAME = FirExtensionPointName("ExistingClassModification")
|
||||||
|
|||||||
@@ -15,6 +15,9 @@ abstract class FirCachesFactory : FirSessionComponent {
|
|||||||
*
|
*
|
||||||
* [FirCache.getValue] should not be called inside [createValue]
|
* [FirCache.getValue] should not be called inside [createValue]
|
||||||
*
|
*
|
||||||
|
* Note, that [createValue] might be called multiple times for the same value,
|
||||||
|
* but all threads will always get the same value
|
||||||
|
*
|
||||||
* Where:
|
* Where:
|
||||||
* [CONTEXT] -- type of value which be used to create value by [createValue]
|
* [CONTEXT] -- type of value which be used to create value by [createValue]
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user