xref: /aosp_15_r20/external/kotlinx.coroutines/kotlinx-coroutines-core/common/src/Unconfined.kt (revision 7a7160fed73afa6648ef8aa100d4a336fe921d9a)
1 package kotlinx.coroutines
2 
3 import kotlin.coroutines.*
4 import kotlin.jvm.*
5 
6 /**
7  * A coroutine dispatcher that is not confined to any specific thread.
8  */
9 internal object Unconfined : CoroutineDispatcher() {
10 
11     @ExperimentalCoroutinesApi
limitedParallelismnull12     override fun limitedParallelism(parallelism: Int): CoroutineDispatcher {
13         throw UnsupportedOperationException("limitedParallelism is not supported for Dispatchers.Unconfined")
14     }
15 
isDispatchNeedednull16     override fun isDispatchNeeded(context: CoroutineContext): Boolean = false
17 
18     override fun dispatch(context: CoroutineContext, block: Runnable) {
19         /** It can only be called by the [yield] function. See also code of [yield] function. */
20         val yieldContext = context[YieldContext]
21         if (yieldContext != null) {
22             // report to "yield" that it is an unconfined dispatcher and don't call "block.run()"
23             yieldContext.dispatcherWasUnconfined = true
24             return
25         }
26         throw UnsupportedOperationException("Dispatchers.Unconfined.dispatch function can only be used by the yield function. " +
27             "If you wrap Unconfined dispatcher in your code, make sure you properly delegate " +
28             "isDispatchNeeded and dispatch calls.")
29     }
30 
toStringnull31     override fun toString(): String = "Dispatchers.Unconfined"
32 }
33 
34 /**
35  * Used to detect calls to [Unconfined.dispatch] from [yield] function.
36  */
37 @PublishedApi
38 internal class YieldContext : AbstractCoroutineContextElement(Key) {
39     companion object Key : CoroutineContext.Key<YieldContext>
40 
41     @JvmField
42     var dispatcherWasUnconfined = false
43 }
44