Eliminate most of TickList's internal logic, greatly speeding it up

This commit is contained in:
DBotThePony 2024-05-16 18:06:09 +07:00
parent 884caba048
commit f416cd69e5
Signed by: DBot
GPG Key ID: DCC23B5715498507

View File

@ -4,24 +4,16 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap
import it.unimi.dsi.fastutil.objects.ObjectAVLTreeSet
import org.apache.logging.log4j.LogManager
import ru.dbotthepony.mc.otm.core.addSorted
import java.util.LinkedList
import java.util.PriorityQueue
import java.util.concurrent.atomic.AtomicInteger
class TickList : ITickable {
private val conditional = ArrayList<IConditionalTickable>()
private val conditionalQueued = ArrayList<IConditionalTickable>()
private val once = ArrayList<ITickable>()
private val onceQueued = ArrayList<ITickable>()
private val always = ArrayList<ITickable>()
private val alwaysQueued = ArrayList<ITickable>()
private val toRemoveFromAlways = ArrayList<ITickable>()
private val tickers = LinkedList<IConditionalTickable>()
private val queuedTickers = ArrayList<IConditionalTickable>()
private val timers = PriorityQueue<Timer>()
private val namedTimers = Object2ObjectOpenHashMap<Any, Timer>(0)
private var shouldTick = false
private val namedTimers = HashMap<Any?, Timer>()
var inTicker = false
private set
@ -37,7 +29,6 @@ class TickList : ITickable {
private set
init {
shouldTick = true
timers.add(this)
}
@ -66,9 +57,9 @@ class TickList : ITickable {
return timer
}
inner class Ticker(parent: ITickable) : ITickable by parent {
inner class Ticker(private val parent: ITickable) : IConditionalTickable {
init {
add(this, always, alwaysQueued)
add(this)
}
var isEnabled = true
@ -77,19 +68,21 @@ class TickList : ITickable {
field = value
if (value) {
add(this, always, alwaysQueued)
add(this)
} else {
alwaysQueued.remove(this)
if (inTicker) {
toRemoveFromAlways.add(this)
} else {
always.remove(this)
}
queuedTickers.remove(this)
}
}
}
override fun tick(): Boolean {
if (!isEnabled)
return false
parent.tick()
return true
}
fun disable() {
isEnabled = false
}
@ -99,20 +92,14 @@ class TickList : ITickable {
}
}
private fun <T : Any> add(value: T, regular: MutableList<T>, queue: MutableList<T>) {
shouldTick = true
fun add(value: IConditionalTickable) {
if (inTicker) {
queue.add(value)
queuedTickers.add(value)
} else {
regular.add(value)
tickers.add(value)
}
}
fun add(ticker: IConditionalTickable) {
add(ticker, conditional, conditionalQueued)
}
fun add(ticker: IConditionalTickable, condition: Boolean, reason: String) {
if (!condition) {
LOGGER.error("Refusing to add tickable $ticker because we $reason", IllegalStateException(reason))
@ -123,7 +110,7 @@ class TickList : ITickable {
}
fun once(ticker: ITickable) {
add(ticker, once, onceQueued)
add(IConditionalTickable { ticker.tick(); false })
}
fun once(ticker: ITickable, condition: Boolean, reason: String) {
@ -136,7 +123,7 @@ class TickList : ITickable {
}
fun always(ticker: ITickable) {
add(ticker, always, alwaysQueued)
add(IConditionalTickable { ticker.tick(); true })
}
fun timer(timerTicks: Int, action: Runnable, condition: Boolean, reason: String): Timer? {
@ -170,59 +157,15 @@ class TickList : ITickable {
}
ticks++
if (!shouldTick) return
inTicker = true
shouldTick = timers.isNotEmpty()
try {
if (conditional.isNotEmpty()) {
shouldTick = true
conditional.removeIf { !it.tick() }
}
tickers.removeIf { !it.tick() }
if (once.isNotEmpty()) {
shouldTick = true
for (ticker in once) ticker.tick()
once.clear()
}
if (toRemoveFromAlways.isNotEmpty()) {
shouldTick = true
for (v in toRemoveFromAlways) always.remove(v)
toRemoveFromAlways.clear()
}
if (always.isNotEmpty()) {
shouldTick = true
for (ticker in always) {
ticker.tick()
}
}
if (alwaysQueued.isNotEmpty()) {
shouldTick = true
always.ensureCapacity(always.size + alwaysQueued.size)
for (v in alwaysQueued) always.add(v) // avoid toArray()
alwaysQueued.clear()
}
if (conditionalQueued.isNotEmpty()) {
shouldTick = true
for (ticker in conditionalQueued) conditional.add(ticker)
conditionalQueued.clear()
}
if (onceQueued.isNotEmpty()) {
shouldTick = true
for (ticker in onceQueued) once.add(ticker)
onceQueued.clear()
if (queuedTickers.isNotEmpty()) {
tickers.addAll(queuedTickers)
queuedTickers.clear()
}
while (timers.isNotEmpty()) {
@ -243,14 +186,8 @@ class TickList : ITickable {
fun clear() {
if (inTicker) throw ConcurrentModificationException()
conditional.clear()
conditionalQueued.clear()
once.clear()
onceQueued.clear()
always.clear()
alwaysQueued.clear()
tickers.clear()
queuedTickers.clear()
timers.clear()
}