From bac5ebcb1200b2f45d097f0b5b2f03a69dcf1606 Mon Sep 17 00:00:00 2001 From: Ilya Kirillov Date: Fri, 13 Nov 2020 20:11:19 +0300 Subject: [PATCH] FIR IDE: use custom thread local value for storing KtFirScopeProvider java.lang.ThreadLocal stores value maps in corresponding threads which causes memory leaks --- .../frontend/api/fir/utils/ThreadLocalDelegate.kt | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/utils/ThreadLocalDelegate.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/utils/ThreadLocalDelegate.kt index 07916982163..8b14f66551f 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/utils/ThreadLocalDelegate.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/utils/ThreadLocalDelegate.kt @@ -5,13 +5,19 @@ package org.jetbrains.kotlin.idea.frontend.api.fir.utils +import java.util.concurrent.ConcurrentHashMap import kotlin.reflect.KProperty -internal class ThreadLocalValue(private val threadLocal: ThreadLocal) { +internal class ThreadLocalValue(private val init: () -> V) { + private val map = ConcurrentHashMap() + @Suppress("NOTHING_TO_INLINE") - inline operator fun getValue(thisRef: Any?, property: KProperty<*>): V = threadLocal.get() + inline operator fun getValue(thisRef: Any?, property: KProperty<*>): V = + map.computeIfAbsent(Thread.currentThread().id) { + init() + } } -internal inline fun threadLocal(crossinline init: () -> T): ThreadLocalValue = - ThreadLocalValue(ThreadLocal.withInitial { init() }) +internal fun threadLocal(init: () -> V): ThreadLocalValue = + ThreadLocalValue(init)