• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3  */
4 
5 @file:JvmMultifileClass
6 @file:JvmName("JobKt")
7 @file:Suppress("DEPRECATION_ERROR", "RedundantUnitReturnType")
8 
9 package kotlinx.coroutines
10 
11 import kotlinx.coroutines.selects.*
12 import kotlin.coroutines.*
13 import kotlin.jvm.*
14 
15 // --------------- core job interfaces ---------------
16 
17 /**
18  * A background job. Conceptually, a job is a cancellable thing with a life-cycle that
19  * culminates in its completion.
20  *
21  * Jobs can be arranged into parent-child hierarchies where cancellation
22  * of a parent leads to immediate cancellation of all its [children] recursively.
23  * Failure of a child with an exception other than [CancellationException] immediately cancels its parent and,
24  * consequently, all its other children. This behavior can be customized using [SupervisorJob].
25  *
26  * The most basic instances of `Job` interface are created like this:
27  *
28  * * **Coroutine job** is created with [launch][CoroutineScope.launch] coroutine builder.
29  *   It runs a specified block of code and completes on completion of this block.
30  * * **[CompletableJob]** is created with a `Job()` factory function.
31  *   It is completed by calling [CompletableJob.complete].
32  *
33  * Conceptually, an execution of a job does not produce a result value. Jobs are launched solely for their
34  * side effects. See [Deferred] interface for a job that produces a result.
35  *
36  * ### Job states
37  *
38  * A job has the following states:
39  *
40  * | **State**                        | [isActive] | [isCompleted] | [isCancelled] |
41  * | -------------------------------- | ---------- | ------------- | ------------- |
42  * | _New_ (optional initial state)   | `false`    | `false`       | `false`       |
43  * | _Active_ (default initial state) | `true`     | `false`       | `false`       |
44  * | _Completing_ (transient state)   | `true`     | `false`       | `false`       |
45  * | _Cancelling_ (transient state)   | `false`    | `false`       | `true`        |
46  * | _Cancelled_ (final state)        | `false`    | `true`        | `true`        |
47  * | _Completed_ (final state)        | `false`    | `true`        | `false`       |
48  *
49  * Usually, a job is created in the _active_ state (it is created and started). However, coroutine builders
50  * that provide an optional `start` parameter create a coroutine in the _new_ state when this parameter is set to
51  * [CoroutineStart.LAZY]. Such a job can be made _active_ by invoking [start] or [join].
52  *
53  * A job is _active_ while the coroutine is working or until [CompletableJob] is completed,
54  * or until it fails or cancelled.
55  *
56  * Failure of an _active_ job with an exception makes it _cancelling_.
57  * A job can be cancelled at any time with [cancel] function that forces it to transition to
58  * the _cancelling_ state immediately. The job becomes _cancelled_  when it finishes executing its work and
59  * all its children complete.
60  *
61  * Completion of an _active_ coroutine's body or a call to [CompletableJob.complete] transitions the job to
62  * the _completing_ state. It waits in the _completing_ state for all its children to complete before
63  * transitioning to the _completed_ state.
64  * Note that _completing_ state is purely internal to the job. For an outside observer a _completing_ job is still
65  * active, while internally it is waiting for its children.
66  *
67  * ```
68  *                                       wait children
69  * +-----+ start  +--------+ complete   +-------------+  finish  +-----------+
70  * | New | -----> | Active | ---------> | Completing  | -------> | Completed |
71  * +-----+        +--------+            +-------------+          +-----------+
72  *                  |  cancel / fail       |
73  *                  |     +----------------+
74  *                  |     |
75  *                  V     V
76  *              +------------+                           finish  +-----------+
77  *              | Cancelling | --------------------------------> | Cancelled |
78  *              +------------+                                   +-----------+
79  * ```
80  *
81  * A `Job` instance in the
82  * [coroutineContext](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines/coroutine-context.html)
83  * represents the coroutine itself.
84  *
85  * ### Cancellation cause
86  *
87  * A coroutine job is said to _complete exceptionally_ when its body throws an exception;
88  * a [CompletableJob] is completed exceptionally by calling [CompletableJob.completeExceptionally].
89  * An exceptionally completed job is cancelled and the corresponding exception becomes the _cancellation cause_ of the job.
90  *
91  * Normal cancellation of a job is distinguished from its failure by the type of this exception that caused its cancellation.
92  * A coroutine that threw [CancellationException] is considered to be _cancelled normally_.
93  * If a cancellation cause is a different exception type, then the job is considered to have _failed_.
94  * When a job has _failed_, then its parent gets cancelled with the exception of the same type,
95  * thus ensuring transparency in delegating parts of the job to its children.
96  *
97  * Note, that [cancel] function on a job only accepts [CancellationException] as a cancellation cause, thus
98  * calling [cancel] always results in a normal cancellation of a job, which does not lead to cancellation
99  * of its parent. This way, a parent can [cancel] its own children (cancelling all their children recursively, too)
100  * without cancelling itself.
101  *
102  * ### Concurrency and synchronization
103  *
104  * All functions on this interface and on all interfaces derived from it are **thread-safe** and can
105  * be safely invoked from concurrent coroutines without external synchronization.
106  *
107  * ### Not stable for inheritance
108  *
109  * **`Job` interface and all its derived interfaces are not stable for inheritance in 3rd party libraries**,
110  * as new methods might be added to this interface in the future, but is stable for use.
111  */
112 public interface Job : CoroutineContext.Element {
113     /**
114      * Key for [Job] instance in the coroutine context.
115      */
116     public companion object Key : CoroutineContext.Key<Job>
117 
118     // ------------ state query ------------
119 
120     /**
121      * Returns the parent of the current job if the parent-child relationship
122      * is established or `null` if the job has no parent or was successfully completed.
123      *
124      * Accesses to this property are not idempotent, the property becomes `null` as soon
125      * as the job is transitioned to its final state, whether it is cancelled or completed,
126      * and all job children are completed.
127      *
128      * For a coroutine, its corresponding job completes as soon as the coroutine itself
129      * and all its children are complete.
130      *
131      * @see [Job] state transitions for additional details.
132      */
133     @ExperimentalCoroutinesApi
134     public val parent: Job?
135 
136     /**
137      * Returns `true` when this job is active -- it was already started and has not completed nor was cancelled yet.
138      * The job that is waiting for its [children] to complete is still considered to be active if it
139      * was not cancelled nor failed.
140      *
141      * See [Job] documentation for more details on job states.
142      */
143     public val isActive: Boolean
144 
145     /**
146      * Returns `true` when this job has completed for any reason. A job that was cancelled or failed
147      * and has finished its execution is also considered complete. Job becomes complete only after
148      * all its [children] complete.
149      *
150      * See [Job] documentation for more details on job states.
151      */
152     public val isCompleted: Boolean
153 
154     /**
155      * Returns `true` if this job was cancelled for any reason, either by explicit invocation of [cancel] or
156      * because it had failed or its child or parent was cancelled.
157      * In the general case, it does not imply that the
158      * job has already [completed][isCompleted], because it may still be finishing whatever it was doing and
159      * waiting for its [children] to complete.
160      *
161      * See [Job] documentation for more details on cancellation and failures.
162      */
163     public val isCancelled: Boolean
164 
165     /**
166      * Returns [CancellationException] that signals the completion of this job. This function is
167      * used by [cancellable][suspendCancellableCoroutine] suspending functions. They throw exception
168      * returned by this function when they suspend in the context of this job and this job becomes _complete_.
169      *
170      * This function returns the original [cancel] cause of this job if that `cause` was an instance of
171      * [CancellationException]. Otherwise (if this job was cancelled with a cause of a different type, or
172      * was cancelled without a cause, or had completed normally), an instance of [CancellationException] is
173      * returned. The [CancellationException.cause] of the resulting [CancellationException] references
174      * the original cancellation cause that was passed to [cancel] function.
175      *
176      * This function throws [IllegalStateException] when invoked on a job that is still active.
177      *
178      * @suppress **This an internal API and should not be used from general code.**
179      */
180     @InternalCoroutinesApi
getCancellationExceptionnull181     public fun getCancellationException(): CancellationException
182 
183     // ------------ state update ------------
184 
185     /**
186      * Starts coroutine related to this job (if any) if it was not started yet.
187      * The result is `true` if this invocation actually started coroutine or `false`
188      * if it was already started or completed.
189      */
190     public fun start(): Boolean
191 
192 
193     /**
194      * Cancels this job with an optional cancellation [cause].
195      * A cause can be used to specify an error message or to provide other details on
196      * the cancellation reason for debugging purposes.
197      * See [Job] documentation for full explanation of cancellation machinery.
198      */
199     public fun cancel(cause: CancellationException? = null)
200 
201     /**
202      * @suppress This method implements old version of JVM ABI. Use [cancel].
203      */
204     @Deprecated(level = DeprecationLevel.HIDDEN, message = "Since 1.2.0, binary compatibility with versions <= 1.1.x")
205     public fun cancel(): Unit = cancel(null)
206 
207     /**
208      * @suppress This method has bad semantics when cause is not a [CancellationException]. Use [cancel].
209      */
210     @Deprecated(level = DeprecationLevel.HIDDEN, message = "Since 1.2.0, binary compatibility with versions <= 1.1.x")
211     public fun cancel(cause: Throwable? = null): Boolean
212 
213     // ------------ parent-child ------------
214 
215     /**
216      * Returns a sequence of this job's children.
217      *
218      * A job becomes a child of this job when it is constructed with this job in its
219      * [CoroutineContext] or using an explicit `parent` parameter.
220      *
221      * A parent-child relation has the following effect:
222      *
223      * * Cancellation of parent with [cancel] or its exceptional completion (failure)
224      *   immediately cancels all its children.
225      * * Parent cannot complete until all its children are complete. Parent waits for all its children to
226      *   complete in _completing_ or _cancelling_ state.
227      * * Uncaught exception in a child, by default, cancels parent. This applies even to
228      *   children created with [async][CoroutineScope.async] and other future-like
229      *   coroutine builders, even though their exceptions are caught and are encapsulated in their result.
230      *   This default behavior can be overridden with [SupervisorJob].
231      */
232     public val children: Sequence<Job>
233 
234     /**
235      * Attaches child job so that this job becomes its parent and
236      * returns a handle that should be used to detach it.
237      *
238      * A parent-child relation has the following effect:
239      * * Cancellation of parent with [cancel] or its exceptional completion (failure)
240      *   immediately cancels all its children.
241      * * Parent cannot complete until all its children are complete. Parent waits for all its children to
242      *   complete in _completing_ or _cancelling_ states.
243      *
244      * **A child must store the resulting [ChildHandle] and [dispose][DisposableHandle.dispose] the attachment
245      * to its parent on its own completion.**
246      *
247      * Coroutine builders and job factory functions that accept `parent` [CoroutineContext] parameter
248      * lookup a [Job] instance in the parent context and use this function to attach themselves as a child.
249      * They also store a reference to the resulting [ChildHandle] and dispose a handle when they complete.
250      *
251      * @suppress This is an internal API. This method is too error prone for public API.
252      */
253     // ChildJob and ChildHandle are made internal on purpose to further deter 3rd-party impl of Job
254     @InternalCoroutinesApi
255     public fun attachChild(child: ChildJob): ChildHandle
256 
257     // ------------ state waiting ------------
258 
259     /**
260      * Suspends the coroutine until this job is complete. This invocation resumes normally (without exception)
261      * when the job is complete for any reason and the [Job] of the invoking coroutine is still [active][isActive].
262      * This function also [starts][Job.start] the corresponding coroutine if the [Job] was still in _new_ state.
263      *
264      * Note that the job becomes complete only when all its children are complete.
265      *
266      * This suspending function is cancellable and **always** checks for a cancellation of the invoking coroutine's Job.
267      * If the [Job] of the invoking coroutine is cancelled or completed when this
268      * suspending function is invoked or while it is suspended, this function
269      * throws [CancellationException].
270      *
271      * In particular, it means that a parent coroutine invoking `join` on a child coroutine throws
272      * [CancellationException] if the child had failed, since a failure of a child coroutine cancels parent by default,
273      * unless the child was launched from within [supervisorScope].
274      *
275      * This function can be used in [select] invocation with [onJoin] clause.
276      * Use [isCompleted] to check for a completion of this job without waiting.
277      *
278      * There is [cancelAndJoin] function that combines an invocation of [cancel] and `join`.
279      */
280     public suspend fun join()
281 
282     /**
283      * Clause for [select] expression of [join] suspending function that selects when the job is complete.
284      * This clause never fails, even if the job completes exceptionally.
285      */
286     public val onJoin: SelectClause0
287 
288     // ------------ low-level state-notification ------------
289 
290     /**
291      * Registers handler that is **synchronously** invoked once on completion of this job.
292      * When the job is already complete, then the handler is immediately invoked
293      * with the job's exception or cancellation cause or `null`. Otherwise, the handler will be invoked once when this
294      * job is complete.
295      *
296      * The meaning of `cause` that is passed to the handler:
297      * * Cause is `null` when the job has completed normally.
298      * * Cause is an instance of [CancellationException] when the job was cancelled _normally_.
299      *   **It should not be treated as an error**. In particular, it should not be reported to error logs.
300      * * Otherwise, the job had _failed_.
301      *
302      * The resulting [DisposableHandle] can be used to [dispose][DisposableHandle.dispose] the
303      * registration of this handler and release its memory if its invocation is no longer needed.
304      * There is no need to dispose the handler after completion of this job. The references to
305      * all the handlers are released when this job completes.
306      *
307      * Installed [handler] should not throw any exceptions. If it does, they will get caught,
308      * wrapped into [CompletionHandlerException], and rethrown, potentially causing crash of unrelated code.
309      *
310      * **Note**: Implementation of `CompletionHandler` must be fast, non-blocking, and thread-safe.
311      * This handler can be invoked concurrently with the surrounding code.
312      * There is no guarantee on the execution context in which the [handler] is invoked.
313      */
314     public fun invokeOnCompletion(handler: CompletionHandler): DisposableHandle
315 
316     /**
317      * Registers handler that is **synchronously** invoked once on cancellation or completion of this job.
318      * when the job was already cancelled and is completed its execution, then the handler is immediately invoked
319      * with the job's cancellation cause or `null` unless [invokeImmediately] is set to false.
320      * Otherwise, handler will be invoked once when this job is cancelled or is complete.
321      *
322      * The meaning of `cause` that is passed to the handler:
323      * * Cause is `null` when the job has completed normally.
324      * * Cause is an instance of [CancellationException] when the job was cancelled _normally_.
325      *   **It should not be treated as an error**. In particular, it should not be reported to error logs.
326      * * Otherwise, the job had _failed_.
327      *
328      * Invocation of this handler on a transition to a _cancelling_ state
329      * is controlled by [onCancelling] boolean parameter.
330      * The handler is invoked when the job becomes _cancelling_ if [onCancelling] parameter is set to `true`.
331      *
332      * The resulting [DisposableHandle] can be used to [dispose][DisposableHandle.dispose] the
333      * registration of this handler and release its memory if its invocation is no longer needed.
334      * There is no need to dispose the handler after completion of this job. The references to
335      * all the handlers are released when this job completes.
336      *
337      * Installed [handler] should not throw any exceptions. If it does, they will get caught,
338      * wrapped into [CompletionHandlerException], and rethrown, potentially causing crash of unrelated code.
339      *
340      * **Note**: This function is a part of internal machinery that supports parent-child hierarchies
341      * and allows for implementation of suspending functions that wait on the Job's state.
342      * This function should not be used in general application code.
343      * Implementation of `CompletionHandler` must be fast, non-blocking, and thread-safe.
344      * This handler can be invoked concurrently with the surrounding code.
345      * There is no guarantee on the execution context in which the [handler] is invoked.
346      *
347      * @param onCancelling when `true`, then the [handler] is invoked as soon as this job transitions to _cancelling_ state;
348      *        when `false` then the [handler] is invoked only when it transitions to _completed_ state.
349      * @param invokeImmediately when `true` and this job is already in the desired state (depending on [onCancelling]),
350      *        then the [handler] is immediately and synchronously invoked and no-op [DisposableHandle] is returned;
351      *        when `false` then no-op [DisposableHandle] is returned, but the [handler] is not invoked.
352      * @param handler the handler.
353      *
354      * @suppress **This an internal API and should not be used from general code.**
355      */
356     @InternalCoroutinesApi
357     public fun invokeOnCompletion(
358         onCancelling: Boolean = false,
359         invokeImmediately: Boolean = true,
360         handler: CompletionHandler): DisposableHandle
361 
362     // ------------ unstable internal API ------------
363 
364     /**
365      * @suppress **Error**: Operator '+' on two Job objects is meaningless.
366      * Job is a coroutine context element and `+` is a set-sum operator for coroutine contexts.
367      * The job to the right of `+` just replaces the job the left of `+`.
368      */
369     @Suppress("DeprecatedCallableAddReplaceWith")
370     @Deprecated(message = "Operator '+' on two Job objects is meaningless. " +
371         "Job is a coroutine context element and `+` is a set-sum operator for coroutine contexts. " +
372         "The job to the right of `+` just replaces the job the left of `+`.",
373         level = DeprecationLevel.ERROR)
374     public operator fun plus(other: Job): Job = other
375 }
376 
377 /**
378  * Creates a job object in an active state.
379  * A failure of any child of this job immediately causes this job to fail, too, and cancels the rest of its children.
380  *
381  * To handle children failure independently of each other use [SupervisorJob].
382  *
383  * If [parent] job is specified, then this job becomes a child job of its parent and
384  * is cancelled when its parent fails or is cancelled. All this job's children are cancelled in this case, too.
385  *
386  * Conceptually, the resulting job works in the same way as the job created by the `launch { body }` invocation
387  * (see [launch]), but without any code in the body. It is active until cancelled or completed. Invocation of
388  * [CompletableJob.complete] or [CompletableJob.completeExceptionally] corresponds to the successful or
389  * failed completion of the body of the coroutine.
390  *
391  * @param parent an optional parent job.
392  */
393 @Suppress("FunctionName")
394 public fun Job(parent: Job? = null): CompletableJob = JobImpl(parent)
395 
396 /** @suppress Binary compatibility only */
397 @Suppress("FunctionName")
398 @Deprecated(level = DeprecationLevel.HIDDEN, message = "Since 1.2.0, binary compatibility with versions <= 1.1.x")
399 @JvmName("Job")
400 public fun Job0(parent: Job? = null): Job = Job(parent)
401 
402 /**
403  * A handle to an allocated object that can be disposed to make it eligible for garbage collection.
404  */
405 public fun interface DisposableHandle {
406     /**
407      * Disposes the corresponding object, making it eligible for garbage collection.
408      * Repeated invocation of this function has no effect.
409      */
410     public fun dispose()
411 }
412 
413 // -------------------- Parent-child communication --------------------
414 
415 /**
416  * A reference that parent receives from its child so that it can report its cancellation.
417  *
418  * @suppress **This is unstable API and it is subject to change.**
419  */
420 @InternalCoroutinesApi
421 @Deprecated(level = DeprecationLevel.ERROR, message = "This is internal API and may be removed in the future releases")
422 public interface ChildJob : Job {
423     /**
424      * Parent is cancelling its child by invoking this method.
425      * Child finds the cancellation cause using [ParentJob.getChildJobCancellationCause].
426      * This method does nothing is the child is already being cancelled.
427      *
428      * @suppress **This is unstable API and it is subject to change.**
429      */
430     @InternalCoroutinesApi
parentCancellednull431     public fun parentCancelled(parentJob: ParentJob)
432 }
433 
434 /**
435  * A reference that child receives from its parent when it is being cancelled by the parent.
436  *
437  * @suppress **This is unstable API and it is subject to change.**
438  */
439 @InternalCoroutinesApi
440 @Deprecated(level = DeprecationLevel.ERROR, message = "This is internal API and may be removed in the future releases")
441 public interface ParentJob : Job {
442     /**
443      * Child job is using this method to learn its cancellation cause when the parent cancels it with [ChildJob.parentCancelled].
444      * This method is invoked only if the child was not already being cancelled.
445      *
446      * Note that [CancellationException] is the method's return type: if child is cancelled by its parent,
447      * then the original exception is **already** handled by either the parent or the original source of failure.
448      *
449      * @suppress **This is unstable API and it is subject to change.**
450      */
451     @InternalCoroutinesApi
452     public fun getChildJobCancellationCause(): CancellationException
453 }
454 
455 /**
456  * A handle that child keep onto its parent so that it is able to report its cancellation.
457  *
458  * @suppress **This is unstable API and it is subject to change.**
459  */
460 @InternalCoroutinesApi
461 @Deprecated(level = DeprecationLevel.ERROR, message = "This is internal API and may be removed in the future releases")
462 public interface ChildHandle : DisposableHandle {
463 
464     /**
465      * Returns the parent of the current parent-child relationship.
466      * @suppress **This is unstable API and it is subject to change.**
467      */
468     @InternalCoroutinesApi
469     public val parent: Job?
470 
471     /**
472      * Child is cancelling its parent by invoking this method.
473      * This method is invoked by the child twice. The first time child report its root cause as soon as possible,
474      * so that all its siblings and the parent can start cancelling their work asap. The second time
475      * child invokes this method when it had aggregated and determined its final cancellation cause.
476      *
477      * @suppress **This is unstable API and it is subject to change.**
478      */
479     @InternalCoroutinesApi
childCancellednull480     public fun childCancelled(cause: Throwable): Boolean
481 }
482 
483 // -------------------- Job extensions --------------------
484 
485 /**
486  * Disposes a specified [handle] when this job is complete.
487  *
488  * This is a shortcut for the following code with slightly more efficient implementation (one fewer object created).
489  * ```
490  * invokeOnCompletion { handle.dispose() }
491  * ```
492  */
493 internal fun Job.disposeOnCompletion(handle: DisposableHandle): DisposableHandle =
494     invokeOnCompletion(handler = DisposeOnCompletion(handle).asHandler)
495 
496 /**
497  * Cancels the job and suspends the invoking coroutine until the cancelled job is complete.
498  *
499  * This suspending function is cancellable and **always** checks for a cancellation of the invoking coroutine's Job.
500  * If the [Job] of the invoking coroutine is cancelled or completed when this
501  * suspending function is invoked or while it is suspended, this function
502  * throws [CancellationException].
503  *
504  * In particular, it means that a parent coroutine invoking `cancelAndJoin` on a child coroutine throws
505  * [CancellationException] if the child had failed, since a failure of a child coroutine cancels parent by default,
506  * unless the child was launched from within [supervisorScope].
507  *
508  * This is a shortcut for the invocation of [cancel][Job.cancel] followed by [join][Job.join].
509  */
510 public suspend fun Job.cancelAndJoin() {
511     cancel()
512     return join()
513 }
514 
515 /**
516  * Cancels all [children][Job.children] jobs of this coroutine using [Job.cancel] for all of them
517  * with an optional cancellation [cause].
518  * Unlike [Job.cancel] on this job as a whole, the state of this job itself is not affected.
519  */
cancelChildrennull520 public fun Job.cancelChildren(cause: CancellationException? = null) {
521     children.forEach { it.cancel(cause) }
522 }
523 
524 /**
525  * @suppress This method implements old version of JVM ABI. Use [cancel].
526  */
527 @Deprecated(level = DeprecationLevel.HIDDEN, message = "Since 1.2.0, binary compatibility with versions <= 1.1.x")
cancelChildrennull528 public fun Job.cancelChildren(): Unit = cancelChildren(null)
529 
530 /**
531  * @suppress This method has bad semantics when cause is not a [CancellationException]. Use [Job.cancelChildren].
532  */
533 @Deprecated(level = DeprecationLevel.HIDDEN, message = "Since 1.2.0, binary compatibility with versions <= 1.1.x")
534 public fun Job.cancelChildren(cause: Throwable? = null) {
535     children.forEach { (it as? JobSupport)?.cancelInternal(cause.orCancellation(this)) }
536 }
537 
538 // -------------------- CoroutineContext extensions --------------------
539 
540 /**
541  * Returns `true` when the [Job] of the coroutine in this context is still active
542  * (has not completed and was not cancelled yet) or the context does not have a [Job] in it.
543  *
544  * Check this property in long-running computation loops to support cancellation
545  * when [CoroutineScope.isActive] is not available:
546  *
547  * ```
548  * while (coroutineContext.isActive) {
549  *     // do some computation
550  * }
551  * ```
552  *
553  * The `coroutineContext.isActive` expression is a shortcut for `get(Job)?.isActive ?: true`.
554  * See [Job.isActive].
555  */
556 public val CoroutineContext.isActive: Boolean
557     get() = get(Job)?.isActive ?: true
558 
559 /**
560  * Cancels [Job] of this context with an optional cancellation cause.
561  * See [Job.cancel] for details.
562  */
cancelnull563 public fun CoroutineContext.cancel(cause: CancellationException? = null) {
564     this[Job]?.cancel(cause)
565 }
566 
567 /**
568  * @suppress This method implements old version of JVM ABI. Use [CoroutineContext.cancel].
569  */
570 @Deprecated(level = DeprecationLevel.HIDDEN, message = "Since 1.2.0, binary compatibility with versions <= 1.1.x")
cancelnull571 public fun CoroutineContext.cancel(): Unit = cancel(null)
572 
573 /**
574  * Ensures that current job is [active][Job.isActive].
575  * If the job is no longer active, throws [CancellationException].
576  * If the job was cancelled, thrown exception contains the original cancellation cause.
577  *
578  * This method is a drop-in replacement for the following code, but with more precise exception:
579  * ```
580  * if (!job.isActive) {
581  *     throw CancellationException()
582  * }
583  * ```
584  */
585 public fun Job.ensureActive(): Unit {
586     if (!isActive) throw getCancellationException()
587 }
588 
589 /**
590  * Ensures that job in the current context is [active][Job.isActive].
591  *
592  * If the job is no longer active, throws [CancellationException].
593  * If the job was cancelled, thrown exception contains the original cancellation cause.
594  * This function does not do anything if there is no [Job] in the context, since such a coroutine cannot be cancelled.
595  *
596  * This method is a drop-in replacement for the following code, but with more precise exception:
597  * ```
598  * if (!isActive) {
599  *     throw CancellationException()
600  * }
601  * ```
602  */
ensureActivenull603 public fun CoroutineContext.ensureActive() {
604     get(Job)?.ensureActive()
605 }
606 
607 /**
608  * Cancels current job, including all its children with a specified diagnostic error [message].
609  * A [cause] can be specified to provide additional details on a cancellation reason for debugging purposes.
610  */
cancelnull611 public fun Job.cancel(message: String, cause: Throwable? = null): Unit = cancel(CancellationException(message, cause))
612 
613 /**
614  * @suppress This method has bad semantics when cause is not a [CancellationException]. Use [CoroutineContext.cancel].
615  */
616 @Deprecated(level = DeprecationLevel.HIDDEN, message = "Since 1.2.0, binary compatibility with versions <= 1.1.x")
617 public fun CoroutineContext.cancel(cause: Throwable? = null): Boolean {
618     val job = this[Job] as? JobSupport ?: return false
619     job.cancelInternal(cause.orCancellation(job))
620     return true
621 }
622 
623 /**
624  * Cancels all children of the [Job] in this context, without touching the state of this job itself
625  * with an optional cancellation cause. See [Job.cancel].
626  * It does not do anything if there is no job in the context or it has no children.
627  */
cancelChildrennull628 public fun CoroutineContext.cancelChildren(cause: CancellationException? = null) {
629     this[Job]?.children?.forEach { it.cancel(cause) }
630 }
631 
632 /**
633  * @suppress This method implements old version of JVM ABI. Use [CoroutineContext.cancelChildren].
634  */
635 @Deprecated(level = DeprecationLevel.HIDDEN, message = "Since 1.2.0, binary compatibility with versions <= 1.1.x")
cancelChildrennull636 public fun CoroutineContext.cancelChildren(): Unit = cancelChildren(null)
637 
638 /**
639  * Retrieves the current [Job] instance from the given [CoroutineContext] or
640  * throws [IllegalStateException] if no job is present in the context.
641  *
642  * This method is a short-cut for `coroutineContext[Job]!!` and should be used only when it is known in advance that
643  * the context does have instance of the job in it.
644  */
645 public val CoroutineContext.job: Job get() = get(Job) ?: error("Current context doesn't contain Job in it: $this")
646 
647 /**
648  * @suppress This method has bad semantics when cause is not a [CancellationException]. Use [CoroutineContext.cancelChildren].
649  */
650 @Deprecated(level = DeprecationLevel.HIDDEN, message = "Since 1.2.0, binary compatibility with versions <= 1.1.x")
651 public fun CoroutineContext.cancelChildren(cause: Throwable? = null) {
652     val job = this[Job] ?: return
653     job.children.forEach { (it as? JobSupport)?.cancelInternal(cause.orCancellation(job)) }
654 }
655 
Throwablenull656 private fun Throwable?.orCancellation(job: Job): Throwable = this ?: JobCancellationException("Job was cancelled", null, job)
657 
658 /**
659  * No-op implementation of [DisposableHandle].
660  * @suppress **This an internal API and should not be used from general code.**
661  */
662 @InternalCoroutinesApi
663 public object NonDisposableHandle : DisposableHandle, ChildHandle {
664 
665     override val parent: Job? get() = null
666 
667     /**
668      * Does not do anything.
669      * @suppress
670      */
671     override fun dispose() {}
672 
673     /**
674      * Returns `false`.
675      * @suppress
676      */
677     override fun childCancelled(cause: Throwable): Boolean = false
678 
679     /**
680      * Returns "NonDisposableHandle" string.
681      * @suppress
682      */
683     override fun toString(): String = "NonDisposableHandle"
684 }
685