1 /*
2 * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3 */
4
5 package kotlinx.coroutines
6
7 import kotlinx.coroutines.internal.multithreadingSupported
8 import kotlin.coroutines.*
9
10 public actual object Dispatchers {
11 public actual val Default: CoroutineDispatcher = createDefaultDispatcherBasedOnMm()
12 public actual val Main: MainCoroutineDispatcher
13 get() = injectedMainDispatcher ?: mainDispatcher
14 public actual val Unconfined: CoroutineDispatcher get() = kotlinx.coroutines.Unconfined // Avoid freezing
15
16 private val mainDispatcher = createMainDispatcher(Default)
17
18 private var injectedMainDispatcher: MainCoroutineDispatcher? = null
19
20 @PublishedApi
injectMainnull21 internal fun injectMain(dispatcher: MainCoroutineDispatcher) {
22 if (!multithreadingSupported) {
23 throw IllegalStateException("Dispatchers.setMain is not supported in Kotlin/Native when new memory model is disabled")
24 }
25 injectedMainDispatcher = dispatcher
26 }
27
28 @PublishedApi
resetInjectedMainnull29 internal fun resetInjectedMain() {
30 injectedMainDispatcher = null
31 }
32 }
33
createMainDispatchernull34 internal expect fun createMainDispatcher(default: CoroutineDispatcher): MainCoroutineDispatcher
35
36 private fun createDefaultDispatcherBasedOnMm(): CoroutineDispatcher {
37 return if (multithreadingSupported) createDefaultDispatcher()
38 else OldDefaultExecutor
39 }
40
takeEventLoopnull41 private fun takeEventLoop(): EventLoopImpl =
42 ThreadLocalEventLoop.currentOrNull() as? EventLoopImpl ?:
43 error("There is no event loop. Use runBlocking { ... } to start one.")
44
45 internal object OldDefaultExecutor : CoroutineDispatcher(), Delay {
46 override fun dispatch(context: CoroutineContext, block: Runnable) =
47 takeEventLoop().dispatch(context, block)
48 override fun scheduleResumeAfterDelay(timeMillis: Long, continuation: CancellableContinuation<Unit>) =
49 takeEventLoop().scheduleResumeAfterDelay(timeMillis, continuation)
50 override fun invokeOnTimeout(timeMillis: Long, block: Runnable, context: CoroutineContext): DisposableHandle =
51 takeEventLoop().invokeOnTimeout(timeMillis, block, context)
52 }
53
54 internal class OldMainDispatcher(private val delegate: CoroutineDispatcher) : MainCoroutineDispatcher() {
55 override val immediate: MainCoroutineDispatcher
56 get() = throw UnsupportedOperationException("Immediate dispatching is not supported on Native")
dispatchnull57 override fun dispatch(context: CoroutineContext, block: Runnable) = delegate.dispatch(context, block)
58 override fun isDispatchNeeded(context: CoroutineContext): Boolean = delegate.isDispatchNeeded(context)
59 override fun dispatchYield(context: CoroutineContext, block: Runnable) = delegate.dispatchYield(context, block)
60 override fun toString(): String = toStringInternalImpl() ?: delegate.toString()
61 }
62