Skip to content

Commit a257f8d

Browse files
committed
SupervisorJob & supervisorScope
Tentative implementation and name, no docs yet Fixes #576
1 parent 73a2583 commit a257f8d

File tree

5 files changed

+99
-3
lines changed

5 files changed

+99
-3
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
package kotlinx.coroutines.experimental
6+
7+
import kotlin.coroutines.experimental.*
8+
9+
@Suppress("FunctionName")
10+
public fun SupervisorJob(parent: Job? = null) : Job = SupervisorJobImpl(parent)
11+
12+
public suspend fun <R> supervisorScope(block: suspend CoroutineScope.() -> R): R {
13+
// todo: optimize implementation to a single allocated object
14+
// todo: fix copy-and-paste with coroutineScope
15+
val owner = SupervisorCoroutine<R>(coroutineContext)
16+
owner.start(CoroutineStart.UNDISPATCHED, owner, block)
17+
owner.join()
18+
if (owner.isCancelled) {
19+
throw owner.getCancellationException().let { it.cause ?: it }
20+
}
21+
val state = owner.state
22+
if (state is CompletedExceptionally) {
23+
throw state.cause
24+
}
25+
@Suppress("UNCHECKED_CAST")
26+
return state as R
27+
28+
}
29+
30+
private class SupervisorJobImpl(parent: Job?) : JobSupport(true) {
31+
init { initParentJobInternal(parent) }
32+
override val onFailComplete get() = true
33+
override val handlesException: Boolean get() = false
34+
override fun childFailed(cause: Throwable): Boolean = false
35+
}
36+
37+
private class SupervisorCoroutine<R>(
38+
parentContext: CoroutineContext
39+
) : AbstractCoroutine<R>(parentContext, true) {
40+
override fun childFailed(cause: Throwable): Boolean = false
41+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
* Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
@file:Suppress("NAMED_ARGUMENTS_NOT_ALLOWED") // KT-21913
6+
7+
package kotlinx.coroutines.experimental
8+
9+
import kotlin.test.*
10+
11+
class SupervisorTest : TestBase() {
12+
@Test
13+
fun testSupervisorJob() = runTest(
14+
unhandled = listOf(
15+
{ it -> it is TestException2 },
16+
{ it -> it is TestException1 }
17+
)
18+
) {
19+
expect(1)
20+
val supervisor = SupervisorJob()
21+
val job1 = launch(supervisor + CoroutineName("job1")) {
22+
expect(2)
23+
yield() // to second child
24+
expect(4)
25+
throw TestException1()
26+
}
27+
val job2 = launch(supervisor + CoroutineName("job2")) {
28+
expect(3)
29+
throw TestException2()
30+
}
31+
joinAll(job1, job2)
32+
finish(5)
33+
assertTrue(job1.isFailed)
34+
assertTrue(job2.isFailed)
35+
}
36+
37+
@Test
38+
fun testSupervisorScope() = runTest(
39+
unhandled = listOf(
40+
{ it -> it is TestException1 },
41+
{ it -> it is TestException2 }
42+
)
43+
) {
44+
val result = supervisorScope {
45+
launch {
46+
throw TestException1()
47+
}
48+
launch {
49+
throw TestException2()
50+
}
51+
"OK"
52+
}
53+
assertEquals("OK", result)
54+
}
55+
56+
private class TestException1 : Exception()
57+
private class TestException2 : Exception()
58+
}

core/kotlinx-coroutines-core/test/TestBase.kt

-1
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,6 @@ public actual open class TestBase actual constructor() {
146146
!unhandled[exCount - 1](e) ->
147147
printError("Unhandled exception was unexpected: $e", e)
148148
}
149-
context[Job]?.cancel(e)
150149
})
151150
} catch (e: Throwable) {
152151
ex = e

js/kotlinx-coroutines-core-js/test/TestBase.kt

-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,6 @@ public actual open class TestBase actual constructor() {
8181
!unhandled[exCount - 1](e) ->
8282
printError("Unhandled exception was unexpected: $e", e)
8383
}
84-
context[Job]?.cancel(e)
8584
}).catch { e ->
8685
ex = e
8786
if (expected != null) {

native/kotlinx-coroutines-core-native/test/TestBase.kt

-1
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,6 @@ public actual open class TestBase actual constructor() {
7676
!unhandled[exCount - 1](e) ->
7777
printError("Unhandled exception was unexpected: $e", e)
7878
}
79-
context[Job]?.cancel(e)
8079
})
8180
} catch (e: Throwable) {
8281
ex = e

0 commit comments

Comments
 (0)