• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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