jvmMain.org.openrndr.CoroutineDispatcher.kt Maven / Gradle / Ivy
The newest version!
package org.openrndr
import io.github.oshai.kotlinlogging.KotlinLogging
import kotlinx.coroutines.*
import kotlin.coroutines.CoroutineContext
private val logger = KotlinLogging.logger {}
private var lastRunTime = -1L
@OptIn(InternalCoroutinesApi::class)
actual class Dispatcher : MainCoroutineDispatcher(), Delay {
private val toRun = mutableListOf()
private val toRunAfter = mutableListOf>()
private val toContinueAfter = mutableListOf>>()
override fun isDispatchNeeded(context: CoroutineContext): Boolean = true
override fun toString(): String {
return "MainCoroutineDispatcher"
}
override fun scheduleResumeAfterDelay(timeMillis: Long, continuation: CancellableContinuation) {
synchronized(toContinueAfter) {
logger.trace { "scheduleResume $timeMillis $continuation" }
toContinueAfter.add(Pair(System.currentTimeMillis() + timeMillis, continuation))
}
}
override val immediate: MainCoroutineDispatcher
get() = this
override fun dispatch(context: CoroutineContext, block: Runnable) {
synchronized(toRun) {
logger.trace { "dispatching $block" }
toRun.add(block)
}
}
val shouldExecute : Boolean
get() {
val time = System.currentTimeMillis()
return toRun.isNotEmpty() || toRunAfter.any { it.first <= time } || toContinueAfter.any { it.first <= time }
}
@OptIn(ExperimentalCoroutinesApi::class)
fun execute() {
lastRunTime = System.currentTimeMillis()
synchronized(toRun) {
val copy = toRun + emptyList()
toRun.clear()
copy.forEach {
logger.trace { "running $it" }
it.run()
}
}
val time = System.currentTimeMillis()
synchronized(toRunAfter) {
val toDo = toRunAfter.filter { it.first <= time }
if (toDo.isNotEmpty()) {
toRunAfter.removeAll { it.first <= time }
}
for ((_, runnable) in toDo) {
logger.trace { "running $runnable" }
runnable.run()
}
}
synchronized(toContinueAfter) {
val toDo = toContinueAfter.filter { it.first <= time }
if (toDo.isNotEmpty()) {
toContinueAfter.removeAll { it.first <= time }
}
for ((_, continuation) in toDo) {
with(continuation) {
logger.trace { "resuming $continuation" }
@Suppress("EXPERIMENTAL_API_USAGE")
resumeUndispatched(Unit)
}
}
}
}
}
suspend fun throttle(timeMillis: Long) {
if ((System.currentTimeMillis() - lastRunTime) > timeMillis) {
delay(1)
}
}
@OptIn(DelicateCoroutinesApi::class)
fun Dispatcher.launch(start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> Unit
): Job = GlobalScope.launch(this, start, block)
© 2015 - 2025 Weber Informatics LLC | Privacy Policy