Skip to content

Commit 31a956f

Browse files
elizarovrecheej
authored andcommitted
Fix ensureAction to work in the empty context case (Kotlin#2119)
Fixes Kotlin#2044
1 parent 9495263 commit 31a956f

File tree

5 files changed

+43
-14
lines changed

5 files changed

+43
-14
lines changed

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

+3-4
Original file line numberDiff line numberDiff line change
@@ -587,10 +587,10 @@ public fun Job.ensureActive(): Unit {
587587

588588
/**
589589
* Ensures that job in the current context is [active][Job.isActive].
590-
* Throws [IllegalStateException] if the context does not have a job in it.
591590
*
592591
* If the job is no longer active, throws [CancellationException].
593592
* If the job was cancelled, thrown exception contains the original cancellation cause.
593+
* This function does not do anything if there is no [Job] in the context, since such a coroutine cannot be cancelled.
594594
*
595595
* This method is a drop-in replacement for the following code, but with more precise exception:
596596
* ```
@@ -599,9 +599,8 @@ public fun Job.ensureActive(): Unit {
599599
* }
600600
* ```
601601
*/
602-
public fun CoroutineContext.ensureActive(): Unit {
603-
val job = get(Job) ?: error("Context cannot be checked for liveness because it does not have a job: $this")
604-
job.ensureActive()
602+
public fun CoroutineContext.ensureActive() {
603+
get(Job)?.ensureActive()
605604
}
606605

607606
/**
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/*
2+
* Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
package kotlinx.coroutines
6+
7+
import kotlinx.coroutines.intrinsics.*
8+
import kotlin.coroutines.*
9+
10+
suspend fun <T> withEmptyContext(block: suspend () -> T): T {
11+
val baseline = Result.failure<T>(IllegalStateException("Block was suspended"))
12+
var result: Result<T> = baseline
13+
block.startCoroutineUnintercepted(Continuation(EmptyCoroutineContext) { result = it })
14+
while (result == baseline) yield()
15+
return result.getOrThrow()
16+
}

kotlinx-coroutines-core/common/test/EnsureActiveTest.kt

+7
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,13 @@ class EnsureActiveTest : TestBase() {
6868
finish(4)
6969
}
7070

71+
@Test
72+
fun testEnsureActiveWithEmptyContext() = runTest {
73+
withEmptyContext {
74+
ensureActive() // should not do anything
75+
}
76+
}
77+
7178
private inline fun checkException(block: () -> Unit) {
7279
val result = runCatching(block)
7380
val exception = result.exceptionOrNull() ?: fail()

kotlinx-coroutines-core/common/test/flow/FlowInvariantsTest.kt

+1-10
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ package kotlinx.coroutines.flow
66

77
import kotlinx.coroutines.*
88
import kotlinx.coroutines.channels.*
9-
import kotlinx.coroutines.intrinsics.*
109
import kotlin.coroutines.*
1110
import kotlin.reflect.*
1211
import kotlin.test.*
@@ -243,16 +242,8 @@ class FlowInvariantsTest : TestBase() {
243242
return result
244243
}
245244

246-
val result = runSuspendFun { collector() }
245+
val result = withEmptyContext { collector() }
247246
assertEquals(2, result)
248247
finish(3)
249248
}
250-
251-
private suspend fun runSuspendFun(block: suspend () -> Int): Int {
252-
val baseline = Result.failure<Int>(IllegalStateException("Block was suspended"))
253-
var result: Result<Int> = baseline
254-
block.startCoroutineUnintercepted(Continuation(EmptyCoroutineContext) { result = it })
255-
while (result == baseline) yield()
256-
return result.getOrThrow()
257-
}
258249
}

kotlinx-coroutines-core/jvm/test/flow/FlowCancellationTest.kt

+16
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,20 @@ class FlowCancellationTest : TestBase() {
4343
job.cancelAndJoin()
4444
finish(3)
4545
}
46+
47+
@Test
48+
fun testFlowWithEmptyContext() = runTest {
49+
expect(1)
50+
withEmptyContext {
51+
val flow = flow {
52+
expect(2)
53+
emit("OK")
54+
}
55+
flow.collect {
56+
expect(3)
57+
assertEquals("OK", it)
58+
}
59+
}
60+
finish(4)
61+
}
4662
}

0 commit comments

Comments
 (0)