Skip to content

Commit 9eaa9c6

Browse files
authored
Introduce CoroutineContext.job extension (#2312)
Fixes #2159
1 parent e941da2 commit 9eaa9c6

File tree

5 files changed

+24
-4
lines changed

5 files changed

+24
-4
lines changed

Diff for: kotlinx-coroutines-core/api/kotlinx-coroutines-core.api

+1
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,7 @@ public final class kotlinx/coroutines/JobKt {
394394
public static final fun cancelFutureOnCompletion (Lkotlinx/coroutines/Job;Ljava/util/concurrent/Future;)Lkotlinx/coroutines/DisposableHandle;
395395
public static final fun ensureActive (Lkotlin/coroutines/CoroutineContext;)V
396396
public static final fun ensureActive (Lkotlinx/coroutines/Job;)V
397+
public static final fun getJob (Lkotlin/coroutines/CoroutineContext;)Lkotlinx/coroutines/Job;
397398
public static final fun isActive (Lkotlin/coroutines/CoroutineContext;)Z
398399
}
399400

Diff for: kotlinx-coroutines-core/common/src/Job.kt

+9
Original file line numberDiff line numberDiff line change
@@ -634,6 +634,15 @@ public fun CoroutineContext.cancelChildren(cause: CancellationException? = null)
634634
@Deprecated(level = DeprecationLevel.HIDDEN, message = "Since 1.2.0, binary compatibility with versions <= 1.1.x")
635635
public fun CoroutineContext.cancelChildren(): Unit = cancelChildren(null)
636636

637+
/**
638+
* Retrieves the current [Job] instance from the given [CoroutineContext] or
639+
* throws [IllegalStateException] if no job is present in the context.
640+
*
641+
* This method is a short-cut for `coroutineContext[Job]!!` and should be used only when it is known in advance that
642+
* the context does have instance of the job in it.
643+
*/
644+
public val CoroutineContext.job: Job get() = get(Job) ?: error("Current context doesn't contain Job in it: $this")
645+
637646
/**
638647
* @suppress This method has bad semantics when cause is not a [CancellationException]. Use [CoroutineContext.cancelChildren].
639648
*/

Diff for: kotlinx-coroutines-core/common/test/EnsureActiveTest.kt renamed to kotlinx-coroutines-core/common/test/JobExtensionsTest.kt

+12-1
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@
44

55
package kotlinx.coroutines
66

7+
import kotlin.coroutines.*
78
import kotlin.test.*
89

9-
class EnsureActiveTest : TestBase() {
10+
class JobExtensionsTest : TestBase() {
1011

1112
private val job = Job()
1213
private val scope = CoroutineScope(job + CoroutineExceptionHandler { _, _ -> })
@@ -81,4 +82,14 @@ class EnsureActiveTest : TestBase() {
8182
assertTrue(exception is JobCancellationException)
8283
assertTrue(exception.cause is TestException)
8384
}
85+
86+
@Test
87+
fun testJobExtension() = runTest {
88+
assertSame(coroutineContext[Job]!!, coroutineContext.job)
89+
assertSame(NonCancellable, NonCancellable.job)
90+
assertSame(job, job.job)
91+
assertFailsWith<IllegalStateException> { EmptyCoroutineContext.job }
92+
assertFailsWith<IllegalStateException> { Dispatchers.Default.job }
93+
assertFailsWith<IllegalStateException> { (Dispatchers.Default + CoroutineName("")).job }
94+
}
8495
}

Diff for: kotlinx-coroutines-core/jvm/src/Interruptible.kt

+1-2
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,7 @@ public suspend fun <T> runInterruptible(
4040

4141
private fun <T> runInterruptibleInExpectedContext(coroutineContext: CoroutineContext, block: () -> T): T {
4242
try {
43-
val job = coroutineContext[Job]!! // withContext always creates a job
44-
val threadState = ThreadState(job)
43+
val threadState = ThreadState(coroutineContext.job)
4544
threadState.setup()
4645
try {
4746
return block()

Diff for: kotlinx-coroutines-core/jvm/src/debug/internal/DebugProbesImpl.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ internal object DebugProbesImpl {
111111
check(isInstalled) { "Debug probes are not installed" }
112112
val jobToStack = capturedCoroutines
113113
.filter { it.delegate.context[Job] != null }
114-
.associateBy({ it.delegate.context[Job]!! }, { it.info })
114+
.associateBy({ it.delegate.context.job }, { it.info })
115115
return buildString {
116116
job.build(jobToStack, this, "")
117117
}

0 commit comments

Comments
 (0)