Allow allocating indices sparsingly in IDAllocator

This commit is contained in:
DBotThePony 2025-04-10 10:12:01 +07:00
parent bb501e2c7e
commit 389d0648b1
Signed by: DBot
GPG Key ID: DCC23B5715498507

View File

@ -1,37 +1,58 @@
package ru.dbotthepony.mc.otm.util
import it.unimi.dsi.fastutil.ints.IntAVLTreeSet
import it.unimi.dsi.fastutil.ints.IntRBTreeSet
class IDAllocator {
private var highestID = 0
private val gaps = IntAVLTreeSet()
private var nextID = -1
private val gaps = IntRBTreeSet()
private val sparseAllocations = IntRBTreeSet()
private fun increaseHighestID(): Int {
while (sparseAllocations.remove(++nextID)) {}
return nextID
}
fun allocate(): Int {
if (gaps.isEmpty()) {
return highestID++
return increaseHighestID()
} else {
return gaps.removeFirst()
}
}
fun allocate(id: Int): Boolean {
if (id < 0) {
return true // not handling negative IDs
} else if (id > nextID) {
sparseAllocations.add(id)
return true
} else if (id == nextID) {
increaseHighestID()
return true
} else {
return gaps.remove(id)
}
}
fun release(id: Int) {
if (id >= 0) {
throw IllegalArgumentException("Invalid ID: $id")
} else if (id >= highestID) {
throw IllegalArgumentException("Not tracking ID: $id (highest known ID is ${highestID - 1})")
if (id < 0) {
return // not handling negative IDs
} else if (sparseAllocations.remove(id)) {
return // was allocated above highest ID
} else if (id > nextID) {
throw IllegalArgumentException("Not tracking ID: $id (highest known ID is ${nextID})")
} else if (id in gaps) {
throw IllegalArgumentException("ID is already free: $id")
}
if (id + 1 == highestID) {
highestID--
} else if (id == nextID) {
nextID--
} else {
gaps.add(id)
check(gaps.add(id))
}
}
fun reset() {
highestID = 0
nextID = -1
gaps.clear()
sparseAllocations.clear()
}
}