Skip to content

Commit 60fd580

Browse files
qwwdfsadelizarov
authored andcommitted
SupervisorCoroutine optimization
1 parent 3e0ca9b commit 60fd580

File tree

2 files changed

+18
-20
lines changed

2 files changed

+18
-20
lines changed

common/kotlinx-coroutines-core-common/src/Supervisor.kt

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@
44

55
package kotlinx.coroutines.experimental
66

7+
import kotlinx.coroutines.experimental.internal.*
8+
import kotlinx.coroutines.experimental.intrinsics.*
79
import 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

5647
private class SupervisorJobImpl(parent: Job?) : JobSupport(true) {
5748
init { initParentJobInternal(parent) }
@@ -62,8 +53,17 @@ private class SupervisorJobImpl(parent: Job?) : JobSupport(true) {
6253
}
6354

6455
private 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
}

common/kotlinx-coroutines-core-common/src/internal/Scopes.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@ internal open class ScopeCoroutine<in T>(
1414
context: CoroutineContext,
1515
@JvmField val uCont: Continuation<T> // unintercepted continuation
1616
) : AbstractCoroutine<T>(context, true) {
17-
override val handlesException: Boolean get() = true // rethrows to invoker
18-
1917
override val defaultResumeMode: Int get() = MODE_DIRECT
2018

2119
@Suppress("UNCHECKED_CAST")

0 commit comments

Comments
 (0)