File tree 4 files changed +48
-1
lines changed
kotlinx-coroutines-core/common
4 files changed +48
-1
lines changed Original file line number Diff line number Diff line change @@ -79,6 +79,15 @@ public abstract class CoroutineDispatcher :
79
79
*/
80
80
public abstract fun dispatch (context : CoroutineContext , block : Runnable )
81
81
82
+ /* *
83
+ * Reserved for [Dispatchers.Unconfined] that returns `false` here because its
84
+ * [dispatch] method throws [UnsupportedOperationException]. It is used in [yield] implementation.
85
+ *
86
+ * @suppress **This an internal API and should not be used from general code.**
87
+ */
88
+ @InternalCoroutinesApi
89
+ public open fun isDispatchSupported (context : CoroutineContext ): Boolean = true
90
+
82
91
/* *
83
92
* Dispatches execution of a runnable `block` onto another thread in the given `context`
84
93
* with a hint for the dispatcher that the current dispatch is triggered by a [yield] call, so that the execution of this
Original file line number Diff line number Diff line change @@ -11,6 +11,7 @@ import kotlin.coroutines.*
11
11
*/
12
12
internal object Unconfined : CoroutineDispatcher() {
13
13
override fun isDispatchNeeded (context : CoroutineContext ): Boolean = false
14
+ override fun isDispatchSupported (context : CoroutineContext ): Boolean = false
14
15
override fun dispatch (context : CoroutineContext , block : Runnable ) { throw UnsupportedOperationException () }
15
16
override fun toString (): String = " Unconfined"
16
17
}
Original file line number Diff line number Diff line change @@ -19,7 +19,9 @@ public suspend fun yield(): Unit = suspendCoroutineUninterceptedOrReturn sc@ { u
19
19
val context = uCont.context
20
20
context.checkCompletion()
21
21
val cont = uCont.intercepted() as ? DispatchedContinuation <Unit > ? : return @sc Unit
22
- if (! cont.dispatcher.isDispatchNeeded(context)) {
22
+ // Special case for Unconfined dispatcher that does not support the concept of "dispatch" and where
23
+ // "dispatchYield" function cannot be used.
24
+ if (! cont.dispatcher.isDispatchSupported(context)) {
23
25
return @sc if (cont.yieldUndispatched()) COROUTINE_SUSPENDED else Unit
24
26
}
25
27
cont.dispatchYield(Unit )
Original file line number Diff line number Diff line change
1
+ /*
2
+ * Copyright 2016-2019 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 kotlin.coroutines.*
8
+ import kotlin.test.*
9
+
10
+ class ImmediateYieldTest : TestBase () {
11
+
12
+ // See https://github.com/Kotlin/kotlinx.coroutines/issues/1474
13
+ @Test
14
+ fun testImmediateYield () = runTest {
15
+ expect(1 )
16
+ launch(ImmediateDispatcher (coroutineContext[ContinuationInterceptor ])) {
17
+ expect(2 )
18
+ yield ()
19
+ expect(4 )
20
+ }
21
+ expect(3 ) // after yield
22
+ yield () // yield back
23
+ finish(5 )
24
+ }
25
+
26
+ // imitate immediate dispatcher
27
+ private class ImmediateDispatcher (job : ContinuationInterceptor ? ) : CoroutineDispatcher() {
28
+ val delegate: CoroutineDispatcher = job as CoroutineDispatcher
29
+
30
+ override fun isDispatchNeeded (context : CoroutineContext ): Boolean = false
31
+
32
+ override fun dispatch (context : CoroutineContext , block : Runnable ) =
33
+ delegate.dispatch(context, block)
34
+ }
35
+ }
You can’t perform that action at this time.
0 commit comments