diff --git a/kotlinx-coroutines-core/api/kotlinx-coroutines-core.api b/kotlinx-coroutines-core/api/kotlinx-coroutines-core.api index d34322c5c3..65a2f519df 100644 --- a/kotlinx-coroutines-core/api/kotlinx-coroutines-core.api +++ b/kotlinx-coroutines-core/api/kotlinx-coroutines-core.api @@ -86,6 +86,7 @@ public final class kotlinx/coroutines/CancellableContinuationKt { public abstract interface class kotlinx/coroutines/ChildHandle : kotlinx/coroutines/DisposableHandle { public abstract fun childCancelled (Ljava/lang/Throwable;)Z + public abstract fun getParent ()Lkotlinx/coroutines/Job; } public abstract interface class kotlinx/coroutines/ChildJob : kotlinx/coroutines/Job { @@ -471,6 +472,7 @@ public final class kotlinx/coroutines/NonDisposableHandle : kotlinx/coroutines/C public static final field INSTANCE Lkotlinx/coroutines/NonDisposableHandle; public fun childCancelled (Ljava/lang/Throwable;)Z public fun dispose ()V + public fun getParent ()Lkotlinx/coroutines/Job; public fun toString ()Ljava/lang/String; } diff --git a/kotlinx-coroutines-core/common/src/Job.kt b/kotlinx-coroutines-core/common/src/Job.kt index fe834b21f6..bc43aff36c 100644 --- a/kotlinx-coroutines-core/common/src/Job.kt +++ b/kotlinx-coroutines-core/common/src/Job.kt @@ -1,5 +1,5 @@ /* - * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. + * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. */ @file:JvmMultifileClass @@ -467,6 +467,14 @@ public interface ParentJob : Job { @InternalCoroutinesApi @Deprecated(level = DeprecationLevel.ERROR, message = "This is internal API and may be removed in the future releases") public interface ChildHandle : DisposableHandle { + + /** + * Returns the parent of the current parent-child relationship. + * @suppress **This is unstable API and it is subject to change.** + */ + @InternalCoroutinesApi + public val parent: Job? + /** * Child is cancelling its parent by invoking this method. * This method is invoked by the child twice. The first time child report its root cause as soon as possible, @@ -660,6 +668,9 @@ private fun Throwable?.orCancellation(job: Job): Throwable = this ?: JobCancella */ @InternalCoroutinesApi public object NonDisposableHandle : DisposableHandle, ChildHandle { + + override val parent: Job? get() = null + /** * Does not do anything. * @suppress diff --git a/kotlinx-coroutines-core/common/src/JobSupport.kt b/kotlinx-coroutines-core/common/src/JobSupport.kt index fca3ee5d84..310610d90f 100644 --- a/kotlinx-coroutines-core/common/src/JobSupport.kt +++ b/kotlinx-coroutines-core/common/src/JobSupport.kt @@ -1459,6 +1459,7 @@ private class InvokeOnCancelling( internal class ChildHandleNode( @JvmField val childJob: ChildJob ) : JobCancellingNode(), ChildHandle { + override val parent: Job get() = job override fun invoke(cause: Throwable?) = childJob.parentCancelled(job) override fun childCancelled(cause: Throwable): Boolean = job.childCancelled(cause) } diff --git a/kotlinx-coroutines-core/common/src/internal/Scopes.kt b/kotlinx-coroutines-core/common/src/internal/Scopes.kt index 9a31c4230c..0a9d24f15f 100644 --- a/kotlinx-coroutines-core/common/src/internal/Scopes.kt +++ b/kotlinx-coroutines-core/common/src/internal/Scopes.kt @@ -21,7 +21,7 @@ internal open class ScopeCoroutine( final override fun getStackTraceElement(): StackTraceElement? = null final override val isScopedCoroutine: Boolean get() = true - internal val parent: Job? = context[Job] + internal val parent: Job? get() = parentHandle?.parent override fun afterCompletion(state: Any?) { // Resume in a cancellable way by default when resuming from another context