From: Lanius Trolling Date: Sun, 28 Apr 2024 16:00:57 +0000 (-0400) Subject: Refactor thread-local ScriptEngine X-Git-Url: https://gitweb.starshipfights.net/?a=commitdiff_plain;h=2ca34342dfd68aee96ef2995d4bd19b6295dd618;p=factbooks Refactor thread-local ScriptEngine --- diff --git a/src/jvmMain/kotlin/info/mechyrdia/lore/ParserPreprocessInclude.kt b/src/jvmMain/kotlin/info/mechyrdia/lore/ParserPreprocessInclude.kt index 20904f6..a4309ab 100644 --- a/src/jvmMain/kotlin/info/mechyrdia/lore/ParserPreprocessInclude.kt +++ b/src/jvmMain/kotlin/info/mechyrdia/lore/ParserPreprocessInclude.kt @@ -5,16 +5,18 @@ import info.mechyrdia.data.FileStorage import info.mechyrdia.data.StoragePath import io.ktor.util.* import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.runInterruptible import kotlinx.coroutines.suspendCancellableCoroutine -import kotlinx.coroutines.withContext import kotlinx.serialization.json.* import java.security.MessageDigest import java.util.concurrent.ConcurrentHashMap +import java.util.concurrent.locks.ReentrantLock import java.util.function.Consumer import javax.script.Compilable import javax.script.CompiledScript import javax.script.ScriptEngineManager import javax.script.SimpleBindings +import kotlin.concurrent.withLock import kotlin.coroutines.* object PreProcessorTemplateLoader { @@ -34,7 +36,8 @@ object PreProcessorTemplateLoader { } object PreProcessorScriptLoader { - private val scriptEngine = ThreadLocal.withInitial { ScriptEngineManager().getEngineByExtension("groovy") } + private val scriptEngine = ScriptEngineManager().getEngineByExtension("groovy") + private val scriptEngineSync = ReentrantLock(true) private val hasher = ThreadLocal.withInitial { MessageDigest.getInstance("SHA-256") } private val cache = ConcurrentHashMap() @@ -42,10 +45,13 @@ object PreProcessorScriptLoader { val scriptFile = StoragePath.scriptDir / "$name.groovy" val script = FileStorage.instance.readFile(scriptFile) ?: return null - val digest = hex(hasher.get().digest(script)) - return withContext(Dispatchers.IO) { + return runInterruptible(Dispatchers.IO) { + val digest = hex(hasher.get().digest(script)) + cache.getOrPut(digest) { - (scriptEngine.get() as Compilable).compile(String(script)) + scriptEngineSync.withLock { + (scriptEngine as Compilable).compile(String(script)) + } } } } @@ -80,7 +86,9 @@ object PreProcessorScriptLoader { bindings["ctx"] = PreProcessorScriptVarContext { jsonToGroovy(env.context[it].toPreProcessJson()) } bindings["finish"] = Consumer(continuation::resume) - script.eval(bindings) + scriptEngineSync.withLock { + script.eval(bindings) + } } }