Skip to content

Commit

Permalink
Use Dispatchers.Main as default delay source where applicable
Browse files Browse the repository at this point in the history
It reduces the number of redundant threads in the system and makes time source predictable across Android/JavaFx applications

Fixes #2972
  • Loading branch information
qwwdfsad committed Nov 17, 2021
1 parent fe9f50b commit 80888af
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 9 deletions.
17 changes: 16 additions & 1 deletion kotlinx-coroutines-core/jvm/src/DefaultExecutor.kt
Expand Up @@ -4,10 +4,25 @@

package kotlinx.coroutines

import kotlinx.coroutines.internal.*
import java.util.concurrent.*
import kotlin.coroutines.*

internal actual val DefaultDelay: Delay = DefaultExecutor
internal actual val DefaultDelay: Delay = initializeDefaultDelay()

private val defaultMainDelayOptIn = systemProp("kotlinx.coroutines.main.delay", true)

private fun initializeDefaultDelay(): Delay {
// Opt-out flag
if (!defaultMainDelayOptIn) return DefaultExecutor
val main = Dispatchers.Main
/*
* When we already are working with UI and Main threads, it makes
* no sense to create a separate thread with timer that cannot be controller
* by the UI runtime.
*/
return if (main.isMissing() || main !is Delay) DefaultExecutor else main
}

@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
internal actual object DefaultExecutor : EventLoopImplBase(), Runnable {
Expand Down
12 changes: 4 additions & 8 deletions ui/kotlinx-coroutines-javafx/src/JavaFxDispatcher.kt
Expand Up @@ -34,22 +34,18 @@ public sealed class JavaFxDispatcher : MainCoroutineDispatcher(), Delay {

/** @suppress */
override fun scheduleResumeAfterDelay(timeMillis: Long, continuation: CancellableContinuation<Unit>) {
val timeline = schedule(timeMillis, TimeUnit.MILLISECONDS, EventHandler {
val timeline = schedule(timeMillis, TimeUnit.MILLISECONDS) {
with(continuation) { resumeUndispatched(Unit) }
})
}
continuation.invokeOnCancellation { timeline.stop() }
}

/** @suppress */
override fun invokeOnTimeout(timeMillis: Long, block: Runnable, context: CoroutineContext): DisposableHandle {
val timeline = schedule(timeMillis, TimeUnit.MILLISECONDS, EventHandler {
val timeline = schedule(timeMillis, TimeUnit.MILLISECONDS) {
block.run()
})
return object : DisposableHandle {
override fun dispose() {
timeline.stop()
}
}
return DisposableHandle { timeline.stop() }
}

private fun schedule(time: Long, unit: TimeUnit, handler: EventHandler<ActionEvent>): Timeline =
Expand Down

0 comments on commit 80888af

Please sign in to comment.