package ru.dbotthepony.kstarbound.lua import it.unimi.dsi.fastutil.ints.IntAVLTreeSet import ru.dbotthepony.kstarbound.lua.userdata.LuaFuture import ru.dbotthepony.kstarbound.lua.userdata.LuaPathFinder import ru.dbotthepony.kstarbound.util.random.random import java.util.concurrent.ConcurrentLinkedQueue import java.util.random.RandomGenerator import kotlin.properties.Delegates class LuaSharedState(val handlesThread: LuaThread) { private val pendingFree = ConcurrentLinkedQueue() private val freeHandles = IntAVLTreeSet() private var nextHandle = 0 // faster code path private var handlesInUse = 0 private val namedHandles = HashMap() var random: RandomGenerator = random() var commonHandles by Delegates.notNull() private set fun initializeHandles(mainThread: LuaThread) { val future = LuaFuture.initializeHandle(mainThread) val pathFinder = LuaPathFinder.initializeHandle(mainThread) commonHandles = CommonHandleRegistry( future = future, pathFinder = pathFinder, ) } fun freeHandle(handle: Int, key: Any?) { pendingFree.add(handle) if (key != null) { namedHandles.remove(key) } } fun cleanup() { if (handlesInUse == 0) return var handle = pendingFree.poll() while (handle != null) { handlesInUse-- freeHandles.add(handle) handlesThread.push() handlesThread.copy(-1, handle) handlesThread.pop() handle = pendingFree.poll() } } fun allocateHandle(name: Any?): LuaHandle { require(name == null || name !in namedHandles) { "Named handle '$name' already exists" } handlesInUse++ if (freeHandles.isEmpty()) { if (nextHandle % 10 == 0) { handlesThread.ensureExtraCapacity(10) } return LuaHandle(this, ++nextHandle, name).also { if (name != null) namedHandles[name] = it } } else { val handle = freeHandles.firstInt() freeHandles.remove(handle) handlesThread.copy(-1, handle) handlesThread.pop() return LuaHandle(this, handle, name).also { if (name != null) namedHandles[name] = it } } } fun getNamedHandle(key: Any): LuaHandle { return namedHandles[key] ?: throw NoSuchElementException("No such handle: $key") } fun findNamedHandle(key: Any): LuaHandle? { return namedHandles[key] } }