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