Skip to content

Commit

Permalink
Use Dispatchers.Main as default delay source where applicable (Kotlin…
Browse files Browse the repository at this point in the history
…#2974)

* Use Dispatchers.Main as default delay source where applicable

It reduces the number of redundant threads in the system and makes time source predictable across Android/JavaFx applications

Fixes Kotlin#2972
  • Loading branch information
qwwdfsad authored and pablobaxter committed Sep 14, 2022
1 parent 5383bf8 commit edc2b5e
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 11 deletions.
2 changes: 0 additions & 2 deletions kotlinx-coroutines-core/common/src/Delay.kt
Expand Up @@ -51,8 +51,6 @@ public interface Delay {
* Schedules invocation of a specified [block] after a specified delay [timeMillis].
* The resulting [DisposableHandle] can be used to [dispose][DisposableHandle.dispose] of this invocation
* request if it is not needed anymore.
*
* This implementation uses a built-in single-threaded scheduled executor service.
*/
public fun invokeOnTimeout(timeMillis: Long, block: Runnable, context: CoroutineContext): DisposableHandle =
DefaultDelay.invokeOnTimeout(timeMillis, block, context)
Expand Down
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 edc2b5e

Please sign in to comment.