File tree 5 files changed +43
-14
lines changed
5 files changed +43
-14
lines changed Original file line number Diff line number Diff line change @@ -587,10 +587,10 @@ public fun Job.ensureActive(): Unit {
587
587
588
588
/* *
589
589
* Ensures that job in the current context is [active][Job.isActive].
590
- * Throws [IllegalStateException] if the context does not have a job in it.
591
590
*
592
591
* If the job is no longer active, throws [CancellationException].
593
592
* 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.
594
594
*
595
595
* This method is a drop-in replacement for the following code, but with more precise exception:
596
596
* ```
@@ -599,9 +599,8 @@ public fun Job.ensureActive(): Unit {
599
599
* }
600
600
* ```
601
601
*/
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()
605
604
}
606
605
607
606
/* *
Original file line number Diff line number Diff line change
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
+ }
Original file line number Diff line number Diff line change @@ -68,6 +68,13 @@ class EnsureActiveTest : TestBase() {
68
68
finish(4 )
69
69
}
70
70
71
+ @Test
72
+ fun testEnsureActiveWithEmptyContext () = runTest {
73
+ withEmptyContext {
74
+ ensureActive() // should not do anything
75
+ }
76
+ }
77
+
71
78
private inline fun checkException (block : () -> Unit ) {
72
79
val result = runCatching(block)
73
80
val exception = result.exceptionOrNull() ? : fail()
Original file line number Diff line number Diff line change @@ -6,7 +6,6 @@ package kotlinx.coroutines.flow
6
6
7
7
import kotlinx.coroutines.*
8
8
import kotlinx.coroutines.channels.*
9
- import kotlinx.coroutines.intrinsics.*
10
9
import kotlin.coroutines.*
11
10
import kotlin.reflect.*
12
11
import kotlin.test.*
@@ -243,16 +242,8 @@ class FlowInvariantsTest : TestBase() {
243
242
return result
244
243
}
245
244
246
- val result = runSuspendFun { collector() }
245
+ val result = withEmptyContext { collector() }
247
246
assertEquals(2 , result)
248
247
finish(3 )
249
248
}
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
- }
258
249
}
Original file line number Diff line number Diff line change @@ -43,4 +43,20 @@ class FlowCancellationTest : TestBase() {
43
43
job.cancelAndJoin()
44
44
finish(3 )
45
45
}
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
+ }
46
62
}
You can’t perform that action at this time.
0 commit comments