KStarbound/src/main/kotlin/ru/dbotthepony/kstarbound/lua/LuaSharedState.kt

90 lines
2.2 KiB
Kotlin

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<Int>()
private val freeHandles = IntAVLTreeSet()
private var nextHandle = 0
// faster code path
private var handlesInUse = 0
private val namedHandles = HashMap<Any, LuaHandle>()
var random: RandomGenerator = random()
var commonHandles by Delegates.notNull<CommonHandleRegistry>()
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]
}
}