44
55package kotlinx.coroutines.experimental
66
7+ import kotlinx.coroutines.experimental.internal.*
8+ import kotlinx.coroutines.experimental.intrinsics.*
79import kotlin.coroutines.experimental.*
10+ import kotlin.coroutines.experimental.intrinsics.*
811
912/* *
1013 * Creates a new _supervisor_ job object in an active state.
@@ -35,23 +38,11 @@ public fun SupervisorJob(parent: Job? = null) : Job = SupervisorJobImpl(parent)
3538 * A failure of the scope itself (exception thrown in the [block] or cancellation) fails the scope with all its children,
3639 * but does not cancel parent job.
3740 */
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)
4645 }
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- }
5546
5647private class SupervisorJobImpl (parent : Job ? ) : JobSupport(true ) {
5748 init { initParentJobInternal(parent) }
@@ -62,8 +53,17 @@ private class SupervisorJobImpl(parent: Job?) : JobSupport(true) {
6253}
6354
6455private class SupervisorCoroutine <R >(
65- parentContext : CoroutineContext
56+ parentContext : CoroutineContext ,
57+ @JvmField val uCont : Continuation <R >
6658) : AbstractCoroutine<R>(parentContext, true ) {
67- override val cancelsParent : Boolean get() = false
59+ override val defaultResumeMode : Int get() = MODE_DIRECT
6860 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+ }
6969}
0 commit comments