Execution spinner for unified and improved spinning

This commit is contained in:
DBotThePony 2024-02-04 13:42:13 +07:00
parent 2f47aa0652
commit 3e2872ea5e
Signed by: DBot
GPG Key ID: DCC23B5715498507

View File

@ -0,0 +1,74 @@
package ru.dbotthepony.kstarbound.util
import ru.dbotthepony.kommons.util.MailboxExecutorService
import ru.dbotthepony.kstarbound.Starbound
import java.util.concurrent.locks.LockSupport
import java.util.function.BooleanSupplier
class ExecutionSpinner(private val executor: MailboxExecutorService, private val spinner: BooleanSupplier, private val timeBetweenFrames: Long) : Runnable {
private var lastRender = System.nanoTime()
private var frameRenderTime = 0L
private val frameRenderTimes = LongArray(60) { 1L }
private var frameRenderIndex = 0
private val renderWaitTimes = LongArray(60) { 1L }
private var renderWaitIndex = 0
val averageRenderWait: Double get() {
var sum = 0.0
for (value in renderWaitTimes)
sum += value
if (sum == 0.0)
return 0.0
sum /= 1_000_000_000.0
return sum / renderWaitTimes.size
}
val averageRenderTime: Double get() {
var sum = 0.0
for (value in frameRenderTimes)
sum += value
if (sum == 0.0)
return 0.0
sum /= 1_000_000_000.0
return sum / frameRenderTimes.size
}
private fun timeUntilNextFrame(): Long {
return Starbound.TICK_TIME_ADVANCE_NANOS - (System.nanoTime() - lastRender) - frameRenderTime
}
fun spin(): Boolean {
var diff = timeUntilNextFrame()
while (diff > 1_000_000L) {
executor.executeQueuedTasks()
diff = timeUntilNextFrame()
if (diff > 1_000_000L) LockSupport.parkNanos(diff - 400_000L)
}
while (diff > 0L) {
executor.executeQueuedTasks()
diff = timeUntilNextFrame()
if (diff > 0L) Thread.yield()
}
val mark = System.nanoTime()
val result = spinner.asBoolean
frameRenderTime = System.nanoTime() - mark
frameRenderTimes[++frameRenderIndex % frameRenderTimes.size] = frameRenderTime
renderWaitTimes[++renderWaitIndex % renderWaitTimes.size] = System.nanoTime() - lastRender
lastRender = System.nanoTime()
return result
}
override fun run() {
while (spin()) {}
}
}