SupervisorCoroutine optimization
diff --git a/common/kotlinx-coroutines-core-common/src/Supervisor.kt b/common/kotlinx-coroutines-core-common/src/Supervisor.kt
index 637ed4e..988162a 100644
--- a/common/kotlinx-coroutines-core-common/src/Supervisor.kt
+++ b/common/kotlinx-coroutines-core-common/src/Supervisor.kt
@@ -4,7 +4,10 @@
package kotlinx.coroutines.experimental
+import kotlinx.coroutines.experimental.internal.*
+import kotlinx.coroutines.experimental.intrinsics.*
import kotlin.coroutines.experimental.*
+import kotlin.coroutines.experimental.intrinsics.*
/**
* Creates a new _supervisor_ job object in an active state.
@@ -35,23 +38,11 @@
* A failure of the scope itself (exception thrown in the [block] or cancellation) fails the scope with all its children,
* but does not cancel parent job.
*/
-public suspend fun <R> supervisorScope(block: suspend CoroutineScope.() -> R): R {
- // todo: optimize implementation to a single allocated object
- // todo: fix copy-and-paste with coroutineScope
- val owner = SupervisorCoroutine<R>(coroutineContext)
- owner.start(CoroutineStart.UNDISPATCHED, owner, block)
- owner.join()
- if (owner.isCancelled) {
- throw owner.getCancellationException().let { it.cause ?: it }
+public suspend fun <R> supervisorScope(block: suspend CoroutineScope.() -> R): R =
+ suspendCoroutineUninterceptedOrReturn { uCont ->
+ val coroutine = SupervisorCoroutine(uCont.context, uCont)
+ coroutine.startUndispatchedOrReturn(coroutine, block)
}
- val state = owner.state
- if (state is CompletedExceptionally) {
- throw state.cause
- }
- @Suppress("UNCHECKED_CAST")
- return state as R
-
-}
private class SupervisorJobImpl(parent: Job?) : JobSupport(true) {
init { initParentJobInternal(parent) }
@@ -62,8 +53,17 @@
}
private class SupervisorCoroutine<R>(
- parentContext: CoroutineContext
+ parentContext: CoroutineContext,
+ @JvmField val uCont: Continuation<R>
) : AbstractCoroutine<R>(parentContext, true) {
- override val cancelsParent: Boolean get() = false
+ override val defaultResumeMode: Int get() = MODE_DIRECT
override fun childCancelled(cause: Throwable): Boolean = false
+
+ @Suppress("UNCHECKED_CAST")
+ internal override fun onCompletionInternal(state: Any?, mode: Int, suppressed: Boolean) {
+ if (state is CompletedExceptionally)
+ uCont.resumeUninterceptedWithExceptionMode(state.cause, mode)
+ else
+ uCont.resumeUninterceptedMode(state as R, mode)
+ }
}
diff --git a/common/kotlinx-coroutines-core-common/src/internal/Scopes.kt b/common/kotlinx-coroutines-core-common/src/internal/Scopes.kt
index fff5fc6..7625c1b 100644
--- a/common/kotlinx-coroutines-core-common/src/internal/Scopes.kt
+++ b/common/kotlinx-coroutines-core-common/src/internal/Scopes.kt
@@ -14,8 +14,6 @@
context: CoroutineContext,
@JvmField val uCont: Continuation<T> // unintercepted continuation
) : AbstractCoroutine<T>(context, true) {
- override val handlesException: Boolean get() = true // rethrows to invoker
-
override val defaultResumeMode: Int get() = MODE_DIRECT
@Suppress("UNCHECKED_CAST")