4
4
5
5
package kotlinx.coroutines.experimental
6
6
7
+ import kotlinx.coroutines.experimental.internal.*
8
+ import kotlinx.coroutines.experimental.intrinsics.*
7
9
import kotlin.coroutines.experimental.*
10
+ import kotlin.coroutines.experimental.intrinsics.*
8
11
9
12
/* *
10
13
* Creates a new _supervisor_ job object in an active state.
@@ -35,23 +38,11 @@ public fun SupervisorJob(parent: Job? = null) : Job = SupervisorJobImpl(parent)
35
38
* A failure of the scope itself (exception thrown in the [block] or cancellation) fails the scope with all its children,
36
39
* but does not cancel parent job.
37
40
*/
38
- public suspend fun <R > supervisorScope (block : suspend CoroutineScope .() -> R ): R {
39
- // todo: optimize implementation to a single allocated object
40
- // todo: fix copy-and-paste with coroutineScope
41
- val owner = SupervisorCoroutine <R >(coroutineContext)
42
- owner.start(CoroutineStart .UNDISPATCHED , owner, block)
43
- owner.join()
44
- if (owner.isCancelled) {
45
- throw owner.getCancellationException().let { it.cause ? : it }
41
+ public suspend fun <R > supervisorScope (block : suspend CoroutineScope .() -> R ): R =
42
+ suspendCoroutineUninterceptedOrReturn { uCont ->
43
+ val coroutine = SupervisorCoroutine (uCont.context, uCont)
44
+ coroutine.startUndispatchedOrReturn(coroutine, block)
46
45
}
47
- val state = owner.state
48
- if (state is CompletedExceptionally ) {
49
- throw state.cause
50
- }
51
- @Suppress(" UNCHECKED_CAST" )
52
- return state as R
53
-
54
- }
55
46
56
47
private class SupervisorJobImpl (parent : Job ? ) : JobSupport(true ) {
57
48
init { initParentJobInternal(parent) }
@@ -62,8 +53,17 @@ private class SupervisorJobImpl(parent: Job?) : JobSupport(true) {
62
53
}
63
54
64
55
private class SupervisorCoroutine <R >(
65
- parentContext : CoroutineContext
56
+ parentContext : CoroutineContext ,
57
+ @JvmField val uCont : Continuation <R >
66
58
) : AbstractCoroutine<R>(parentContext, true ) {
67
- override val cancelsParent : Boolean get() = false
59
+ override val defaultResumeMode : Int get() = MODE_DIRECT
68
60
override fun childCancelled (cause : Throwable ): Boolean = false
61
+
62
+ @Suppress(" UNCHECKED_CAST" )
63
+ internal override fun onCompletionInternal (state : Any? , mode : Int , suppressed : Boolean ) {
64
+ if (state is CompletedExceptionally )
65
+ uCont.resumeUninterceptedWithExceptionMode(state.cause, mode)
66
+ else
67
+ uCont.resumeUninterceptedMode(state as R , mode)
68
+ }
69
69
}
0 commit comments