xref: /aosp_15_r20/external/kotlinx.coroutines/kotlinx-coroutines-core/common/src/Supervisor.kt (revision 7a7160fed73afa6648ef8aa100d4a336fe921d9a)

<lambda>null1 @file:OptIn(ExperimentalContracts::class)
2 @file:Suppress("DEPRECATION_ERROR")
3 
4 package kotlinx.coroutines
5 
6 import kotlinx.coroutines.internal.*
7 import kotlinx.coroutines.intrinsics.*
8 import kotlin.contracts.*
9 import kotlin.coroutines.*
10 import kotlin.coroutines.intrinsics.*
11 import kotlin.jvm.*
12 
13 /**
14  * Creates a _supervisor_ job object in an active state.
15  * Children of a supervisor job can fail independently of each other.
16  *
17  * A failure or cancellation of a child does not cause the supervisor job to fail and does not affect its other children,
18  * so a supervisor can implement a custom policy for handling failures of its children:
19  *
20  * - A failure of a child job that was created using [launch][CoroutineScope.launch] can be handled via [CoroutineExceptionHandler] in the context.
21  * - A failure of a child job that was created using [async][CoroutineScope.async] can be handled via [Deferred.await] on the resulting deferred value.
22  *
23  * If a [parent] job is specified, then this supervisor job becomes a child job of [parent] and is cancelled when the
24  * parent fails or is cancelled. All this supervisor's children are cancelled in this case, too.
25  */
26 @Suppress("FunctionName")
27 public fun SupervisorJob(parent: Job? = null) : CompletableJob = SupervisorJobImpl(parent)
28 
29 /** @suppress Binary compatibility only */
30 @Suppress("FunctionName")
31 @Deprecated(level = DeprecationLevel.HIDDEN, message = "Since 1.2.0, binary compatibility with versions <= 1.1.x")
32 @JvmName("SupervisorJob")
33 public fun SupervisorJob0(parent: Job? = null) : Job = SupervisorJob(parent)
34 
35 /**
36  * Creates a [CoroutineScope] with [SupervisorJob] and calls the specified suspend [block] with this scope.
37  * The provided scope inherits its [coroutineContext][CoroutineScope.coroutineContext] from the outer scope, using the
38  * [Job] from that context as the parent for the new [SupervisorJob].
39  * This function returns as soon as the given block and all its child coroutines are completed.
40  *
41  * Unlike [coroutineScope], a failure of a child does not cause this scope to fail and does not affect its other children,
42  * so a custom policy for handling failures of its children can be implemented. See [SupervisorJob] for additional details.
43  *
44  * If an exception happened in [block], then the supervisor job is failed and all its children are cancelled.
45  * If the current coroutine was cancelled, then both the supervisor job itself and all its children are cancelled.
46  *
47  * The method may throw a [CancellationException] if the current job was cancelled externally,
48  * or rethrow an exception thrown by the given [block].
49  */
50 public suspend fun <R> supervisorScope(block: suspend CoroutineScope.() -> R): R {
51     contract {
52         callsInPlace(block, InvocationKind.EXACTLY_ONCE)
53     }
54     return suspendCoroutineUninterceptedOrReturn { uCont ->
55         val coroutine = SupervisorCoroutine(uCont.context, uCont)
56         coroutine.startUndispatchedOrReturn(coroutine, block)
57     }
58 }
59 
60 private class SupervisorJobImpl(parent: Job?) : JobImpl(parent) {
childCancellednull61     override fun childCancelled(cause: Throwable): Boolean = false
62 }
63 
64 private class SupervisorCoroutine<in T>(
65     context: CoroutineContext,
66     uCont: Continuation<T>
67 ) : ScopeCoroutine<T>(context, uCont) {
68     override fun childCancelled(cause: Throwable): Boolean = false
69 }
70