blob: b0a31882a6123be3e7d0191913472b0ba79e6328 [file] [log] [blame]
Roman Elizarovf16fd272017-02-07 11:26:00 +03001/*
Roman Elizarovcd2a8d72019-02-12 15:17:17 +03002 * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
Roman Elizarovf16fd272017-02-07 11:26:00 +03003 */
4
Roman Elizarovaa461cf2018-04-11 13:20:29 +03005@file:JvmMultifileClass
6@file:JvmName("JobKt")
Vsevolod Tolstopyatovb058ba12018-10-17 15:15:17 +03007@file:Suppress("DEPRECATION_ERROR", "RedundantUnitReturnType")
Roman Elizarovf161c9f2018-02-07 23:27:10 +03008
Roman Elizarov0950dfa2018-07-13 10:33:25 +03009package kotlinx.coroutines
Roman Elizarov3754f952017-01-18 20:47:54 +030010
Roman Elizarov0950dfa2018-07-13 10:33:25 +030011import kotlinx.coroutines.selects.*
12import kotlin.coroutines.*
Vsevolod Tolstopyatov36c3ba12018-10-14 23:45:28 +030013import kotlin.jvm.*
Roman Elizarov3754f952017-01-18 20:47:54 +030014
15// --------------- core job interfaces ---------------
16
17/**
Roman Elizarovecbc85c2018-09-14 12:52:50 +030018 * A background job. Conceptually, a job is a cancellable thing with a life-cycle that
Roman Elizarov852fae52018-09-25 20:13:24 +030019 * culminates in its completion.
20 *
21 * Jobs can be arranged into parent-child hierarchies where cancellation
Yanis Batura8140cfe2019-04-27 21:31:14 +070022 * of a parent leads to immediate cancellation of all its [children]. Failure or cancellation of a child
23 * with an exception other than [CancellationException] immediately cancels its parent. This way, a parent
Roman Elizarov852fae52018-09-25 20:13:24 +030024 * can [cancel] its own children (including all their children recursively) without cancelling itself.
Roman Elizarov44ba4b12017-01-25 11:37:54 +030025 *
Roman Elizarovc32579e2018-09-09 19:21:43 +030026 * The most basic instances of [Job] are created with [launch][CoroutineScope.launch] coroutine builder or with a
Inego39f92ca2019-04-21 13:30:55 +070027 * `Job()` factory function. By default, a failure of any of the job's children leads to an immediate failure
Roman Elizarov21f171c2018-09-23 19:16:04 +030028 * of its parent and cancellation of the rest of its children. This behavior can be customized using [SupervisorJob].
29 *
Roman Elizarovecbc85c2018-09-14 12:52:50 +030030 * Conceptually, an execution of the job does not produce a result value. Jobs are launched solely for their
31 * side-effects. See [Deferred] interface for a job that produces a result.
Roman Elizarov32d95322017-02-09 15:57:31 +030032 *
Roman Elizarovd82b3a92017-06-23 21:52:08 +030033 * A job has the following states:
Roman Elizarov32d95322017-02-09 15:57:31 +030034 *
Roman Elizarov6685fd02018-09-25 13:23:53 +030035 * | **State** | [isActive] | [isCompleted] | [isCancelled] |
36 * | -------------------------------- | ---------- | ------------- | ------------- |
37 * | _New_ (optional initial state) | `false` | `false` | `false` |
38 * | _Active_ (default initial state) | `true` | `false` | `false` |
39 * | _Completing_ (transient state) | `true` | `false` | `false` |
40 * | _Cancelling_ (transient state) | `false` | `false` | `true` |
41 * | _Cancelled_ (final state) | `false` | `true` | `true` |
42 * | _Completed_ (final state) | `false` | `true` | `false` |
Roman Elizarovd82b3a92017-06-23 21:52:08 +030043 *
44 * Usually, a job is created in _active_ state (it is created and started). However, coroutine builders
45 * that provide an optional `start` parameter create a coroutine in _new_ state when this parameter is set to
46 * [CoroutineStart.LAZY]. Such a job can be made _active_ by invoking [start] or [join].
47 *
Roman Elizarov852fae52018-09-25 20:13:24 +030048 * A job is _active_ while the coroutine is working. Failure of the job with exception makes it _cancelling_.
Inego39f92ca2019-04-21 13:30:55 +070049 * A job can be cancelled at any time with [cancel] function that forces it to transition to
50 * _cancelling_ state immediately. The job becomes _cancelled_ when it finishes executing its work.
Roman Elizarovd82b3a92017-06-23 21:52:08 +030051 *
52 * ```
Roman Elizarovecbc85c2018-09-14 12:52:50 +030053 * wait children
54 * +-----+ start +--------+ complete +-------------+ finish +-----------+
55 * | New | -----> | Active | ---------> | Completing | -------> | Completed |
56 * +-----+ +--------+ +-------------+ +-----------+
Roman Elizarov852fae52018-09-25 20:13:24 +030057 * | cancel / fail |
Roman Elizarov6685fd02018-09-25 13:23:53 +030058 * | +----------------+
Roman Elizarovecbc85c2018-09-14 12:52:50 +030059 * | |
60 * V V
61 * +------------+ finish +-----------+
62 * | Cancelling | --------------------------------> | Cancelled |
63 * +------------+ +-----------+
Roman Elizarovd82b3a92017-06-23 21:52:08 +030064 * ```
Roman Elizarovb7c46de2017-02-08 12:35:24 +030065 *
Roman Elizarovecbc85c2018-09-14 12:52:50 +030066 * A `Job` instance in the
Roman Elizarov0950dfa2018-07-13 10:33:25 +030067 * [coroutineContext](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines/coroutine-context.html)
Roman Elizarov9fe5f462018-02-21 19:05:52 +030068 * represents the coroutine itself.
Roman Elizarov3754f952017-01-18 20:47:54 +030069 *
Roman Elizarov6685fd02018-09-25 13:23:53 +030070 * A job can have a _parent_ job. A job with a parent is cancelled when its parent is cancelled.
71 * Parent job waits in _completing_ or _cancelling_ state for all its children to complete before finishing.
Inegoebe519a2019-04-21 13:22:27 +070072 * Note that _completing_ state is purely internal to the job. For an outside observer a _completing_ job is still
Roman Elizarovecbc85c2018-09-14 12:52:50 +030073 * active, while internally it is waiting for its children.
Roman Elizarov3754f952017-01-18 20:47:54 +030074 *
Roman Elizarov852fae52018-09-25 20:13:24 +030075 * Normal cancellation of a job is distinguished from its failure by the type of its cancellation exception cause.
76 * If the cause of cancellation is [CancellationException], then the job is considered to be _cancelled normally_.
77 * This usually happens when [cancel] is invoked without additional parameters. If the cause of cancellation is
78 * a different exception, then the job is considered to have _failed_. This usually happens when the code of the job
79 * encounters some problem and throws an exception.
80 *
Roman Elizarovb7c46de2017-02-08 12:35:24 +030081 * All functions on this interface and on all interfaces derived from it are **thread-safe** and can
82 * be safely invoked from concurrent coroutines without external synchronization.
Roman Elizarov3754f952017-01-18 20:47:54 +030083 */
Roman Elizarovaa461cf2018-04-11 13:20:29 +030084public interface Job : CoroutineContext.Element {
Roman Elizarovd528e3e2017-01-23 15:40:05 +030085 /**
86 * Key for [Job] instance in the coroutine context.
87 */
Roman Elizarovaa461cf2018-04-11 13:20:29 +030088 public companion object Key : CoroutineContext.Key<Job> {
Roman Elizarov11c140a2017-07-21 21:12:55 +030089 init {
90 /*
91 * Here we make sure that CoroutineExceptionHandler is always initialized in advance, so
92 * that if a coroutine fails due to StackOverflowError we don't fail to report this error
93 * trying to initialize CoroutineExceptionHandler
94 */
95 CoroutineExceptionHandler
96 }
Roman Elizarov3754f952017-01-18 20:47:54 +030097 }
98
Roman Elizarovd82b3a92017-06-23 21:52:08 +030099 // ------------ state query ------------
100
Roman Elizarov3754f952017-01-18 20:47:54 +0300101 /**
Roman Elizarov852fae52018-09-25 20:13:24 +0300102 * Returns `true` when this job is active -- it was already started and has not completed nor was cancelled yet.
Roman Elizarov3e387b82017-12-04 13:49:11 +0300103 * The job that is waiting for its [children] to complete is still considered to be active if it
Roman Elizarov852fae52018-09-25 20:13:24 +0300104 * was not cancelled nor failed.
105 *
106 * See [Job] documentation for more details on job states.
Roman Elizarov3754f952017-01-18 20:47:54 +0300107 */
Roman Elizarovaa461cf2018-04-11 13:20:29 +0300108 public val isActive: Boolean
Roman Elizarov3754f952017-01-18 20:47:54 +0300109
110 /**
Roman Elizarov852fae52018-09-25 20:13:24 +0300111 * Returns `true` when this job has completed for any reason. A job that was cancelled or failed
Roman Elizarovecbc85c2018-09-14 12:52:50 +0300112 * and has finished its execution is also considered complete. Job becomes complete only after
Roman Elizarov3e387b82017-12-04 13:49:11 +0300113 * all its [children] complete.
Roman Elizarov852fae52018-09-25 20:13:24 +0300114 *
115 * See [Job] documentation for more details on job states.
Roman Elizarov32d95322017-02-09 15:57:31 +0300116 */
Roman Elizarovaa461cf2018-04-11 13:20:29 +0300117 public val isCompleted: Boolean
Roman Elizarov32d95322017-02-09 15:57:31 +0300118
119 /**
Roman Elizarov6685fd02018-09-25 13:23:53 +0300120 * Returns `true` if this job was cancelled for any reason, either by explicit invocation of [cancel] or
Roman Elizarov852fae52018-09-25 20:13:24 +0300121 * because it had failed or its child or parent was cancelled.
Roman Elizarovecbc85c2018-09-14 12:52:50 +0300122 * In the general case, it does not imply that the
123 * job has already [completed][isCompleted], because it may still be finishing whatever it was doing and
124 * waiting for its [children] to complete.
Roman Elizarov852fae52018-09-25 20:13:24 +0300125 *
126 * See [Job] documentation for more details on cancellation and failures.
Roman Elizarovecbc85c2018-09-14 12:52:50 +0300127 */
Roman Elizarovaa461cf2018-04-11 13:20:29 +0300128 public val isCancelled: Boolean
Roman Elizarovd82b3a92017-06-23 21:52:08 +0300129
130 /**
Roman Elizarov9832d3d2017-12-20 11:03:21 +0300131 * Returns [CancellationException] that signals the completion of this job. This function is
132 * used by [cancellable][suspendCancellableCoroutine] suspending functions. They throw exception
133 * returned by this function when they suspend in the context of this job and this job becomes _complete_.
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300134 *
Roman Elizarov9832d3d2017-12-20 11:03:21 +0300135 * This function returns the original [cancel] cause of this job if that `cause` was an instance of
136 * [CancellationException]. Otherwise (if this job was cancelled with a cause of a different type, or
Vsevolod Tolstopyatov149ba482018-09-24 20:28:02 +0300137 * was cancelled without a cause, or had completed normally), an instance of [CancellationException] is
138 * returned. The [CancellationException.cause] of the resulting [CancellationException] references
Roman Elizarov9832d3d2017-12-20 11:03:21 +0300139 * the original cancellation cause that was passed to [cancel] function.
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300140 *
Roman Elizarovecbc85c2018-09-14 12:52:50 +0300141 * This function throws [IllegalStateException] when invoked on a job that is still active.
142 *
Roman Elizarov27b8f452018-09-20 21:23:41 +0300143 * @suppress **This an internal API and should not be used from general code.**
Roman Elizarovd82b3a92017-06-23 21:52:08 +0300144 */
Roman Elizarov27b8f452018-09-20 21:23:41 +0300145 @InternalCoroutinesApi
Roman Elizarovaa461cf2018-04-11 13:20:29 +0300146 public fun getCancellationException(): CancellationException
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300147
Roman Elizarovd82b3a92017-06-23 21:52:08 +0300148 // ------------ state update ------------
149
150 /**
Roman Elizarov32d95322017-02-09 15:57:31 +0300151 * Starts coroutine related to this job (if any) if it was not started yet.
152 * The result `true` if this invocation actually started coroutine or `false`
153 * if it was already started or completed.
154 */
Roman Elizarovaa461cf2018-04-11 13:20:29 +0300155 public fun start(): Boolean
Roman Elizarov32d95322017-02-09 15:57:31 +0300156
Roman Elizarov27b8f452018-09-20 21:23:41 +0300157
158 /**
Roman Elizarov0aad8f12019-03-01 12:08:43 +0300159 * Cancels this job with an optional cancellation [cause].
160 * A cause can be used to specify an error message or to provide other details on
Inego596187e2019-04-21 14:21:53 +0700161 * the cancellation reason for debugging purposes.
Vsevolod Tolstopyatovb058ba12018-10-17 15:15:17 +0300162 * See [Job] documentation for full explanation of cancellation machinery.
Roman Elizarov3754f952017-01-18 20:47:54 +0300163 */
Roman Elizarov0aad8f12019-03-01 12:08:43 +0300164 public fun cancel(cause: CancellationException? = null)
Vsevolod Tolstopyatovb058ba12018-10-17 15:15:17 +0300165
166 /**
Roman Elizarov0aad8f12019-03-01 12:08:43 +0300167 * @suppress This method implements old version of JVM ABI. Use [cancel].
Vsevolod Tolstopyatovb058ba12018-10-17 15:15:17 +0300168 */
Roman Elizarov73b456b2019-03-06 17:18:27 +0300169 @Deprecated(level = DeprecationLevel.HIDDEN, message = "Since 1.2.0, binary compatibility with versions <= 1.1.x")
Roman Elizarov0aad8f12019-03-01 12:08:43 +0300170 public fun cancel() = cancel(null)
171
172 /**
173 * @suppress This method has bad semantics when cause is not a [CancellationException]. Use [cancel].
174 */
Roman Elizarov73b456b2019-03-06 17:18:27 +0300175 @Deprecated(level = DeprecationLevel.HIDDEN, message = "Since 1.2.0, binary compatibility with versions <= 1.1.x")
Roman Elizarovaa461cf2018-04-11 13:20:29 +0300176 public fun cancel(cause: Throwable? = null): Boolean
Roman Elizarov3754f952017-01-18 20:47:54 +0300177
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300178 // ------------ parent-child ------------
179
Roman Elizarovecbc85c2018-09-14 12:52:50 +0300180 /**
Roman Elizarov3e387b82017-12-04 13:49:11 +0300181 * Returns a sequence of this job's children.
182 *
183 * A job becomes a child of this job when it is constructed with this job in its
184 * [CoroutineContext] or using an explicit `parent` parameter.
185 *
186 * A parent-child relation has the following effect:
187 *
188 * * Cancellation of parent with [cancel] or its exceptional completion (failure)
189 * immediately cancels all its children.
190 * * Parent cannot complete until all its children are complete. Parent waits for all its children to
191 * complete in _completing_ or _cancelling_ state.
192 * * Uncaught exception in a child, by default, cancels parent. In particular, this applies to
Inegoebe519a2019-04-21 13:22:27 +0700193 * children created with [launch][CoroutineScope.launch] coroutine builder. Note that
Roman Elizarovc32579e2018-09-09 19:21:43 +0300194 * [async][CoroutineScope.async] and other future-like
Roman Elizarov3e387b82017-12-04 13:49:11 +0300195 * coroutine builders do not have uncaught exceptions by definition, since all their exceptions are
196 * caught and are encapsulated in their result.
197 */
Roman Elizarovaa461cf2018-04-11 13:20:29 +0300198 public val children: Sequence<Job>
Roman Elizarov3e387b82017-12-04 13:49:11 +0300199
200 /**
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300201 * Attaches child job so that this job becomes its parent and
202 * returns a handle that should be used to detach it.
203 *
204 * A parent-child relation has the following effect:
Roman Elizarova36ab942017-10-07 05:44:48 -0700205 * * Cancellation of parent with [cancel] or its exceptional completion (failure)
Roman Elizarov852fae52018-09-25 20:13:24 +0300206 * immediately cancels all its children.
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300207 * * Parent cannot complete until all its children are complete. Parent waits for all its children to
Roman Elizarov6685fd02018-09-25 13:23:53 +0300208 * complete in _completing_ or _cancelling_ states.
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300209 *
Roman Elizarovf7a63342018-09-25 00:26:25 +0300210 * **A child must store the resulting [ChildHandle] and [dispose][DisposableHandle.dispose] the attachment
Roman Elizarov447b88a2017-12-01 15:37:48 +0300211 * to its parent on its own completion.**
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300212 *
213 * Coroutine builders and job factory functions that accept `parent` [CoroutineContext] parameter
214 * lookup a [Job] instance in the parent context and use this function to attach themselves as a child.
Roman Elizarovf7a63342018-09-25 00:26:25 +0300215 * They also store a reference to the resulting [ChildHandle] and dispose a handle when they complete.
Roman Elizarov447b88a2017-12-01 15:37:48 +0300216 *
217 * @suppress This is an internal API. This method is too error prone for public API.
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300218 */
Roman Elizarovf7a63342018-09-25 00:26:25 +0300219 // ChildJob and ChildHandle are made internal on purpose to further deter 3rd-party impl of Job
Roman Elizarov27b8f452018-09-20 21:23:41 +0300220 @InternalCoroutinesApi
Roman Elizarovf7a63342018-09-25 00:26:25 +0300221 public fun attachChild(child: ChildJob): ChildHandle
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300222
Roman Elizarovd82b3a92017-06-23 21:52:08 +0300223 // ------------ state waiting ------------
224
225 /**
Inego596187e2019-04-21 14:21:53 +0700226 * Suspends the coroutine until this job is complete. This invocation resumes normally (without exception)
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300227 * when the job is complete for any reason and the [Job] of the invoking coroutine is still [active][isActive].
228 * This function also [starts][Job.start] the corresponding coroutine if the [Job] was still in _new_ state.
Roman Elizarovd82b3a92017-06-23 21:52:08 +0300229 *
Inegoebe519a2019-04-21 13:22:27 +0700230 * Note that the job becomes complete only when all its children are complete.
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300231 *
Inego596187e2019-04-21 14:21:53 +0700232 * This suspending function is cancellable and **always** checks for a cancellation of the invoking coroutine's Job.
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300233 * If the [Job] of the invoking coroutine is cancelled or completed when this
234 * suspending function is invoked or while it is suspended, this function
235 * throws [CancellationException].
236 *
237 * In particular, it means that a parent coroutine invoking `join` on a child coroutine that was started using
238 * `launch(coroutineContext) { ... }` builder throws [CancellationException] if the child
Inego596187e2019-04-21 14:21:53 +0700239 * had crashed, unless a non-standard [CoroutineExceptionHandler] is installed in the context.
Roman Elizarovd82b3a92017-06-23 21:52:08 +0300240 *
Roman Elizarovdb0e22d2017-08-29 18:15:57 +0300241 * This function can be used in [select] invocation with [onJoin] clause.
Inego596187e2019-04-21 14:21:53 +0700242 * Use [isCompleted] to check for a completion of this job without waiting.
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300243 *
244 * There is [cancelAndJoin] function that combines an invocation of [cancel] and `join`.
Roman Elizarovd82b3a92017-06-23 21:52:08 +0300245 */
Roman Elizarovaa461cf2018-04-11 13:20:29 +0300246 public suspend fun join()
Roman Elizarovd82b3a92017-06-23 21:52:08 +0300247
Roman Elizarovdb0e22d2017-08-29 18:15:57 +0300248 /**
249 * Clause for [select] expression of [join] suspending function that selects when the job is complete.
250 * This clause never fails, even if the job completes exceptionally.
251 */
252 public val onJoin: SelectClause0
253
Roman Elizarovd82b3a92017-06-23 21:52:08 +0300254 // ------------ low-level state-notification ------------
255
Roman Elizarov00e90dd2017-12-22 14:38:21 +0300256 /**
Roman Elizarove1c0b652017-12-01 14:02:57 +0300257 * Registers handler that is **synchronously** invoked once on completion of this job.
Yanis Batura8140cfe2019-04-27 21:31:14 +0700258 * When the job is already complete, then the handler is immediately invoked
259 * with the job's exception or cancellation cause or `null`. Otherwise, the handler will be invoked once when this
Roman Elizarove1c0b652017-12-01 14:02:57 +0300260 * job is complete.
261 *
Roman Elizarove89cd682018-04-25 13:03:40 +0300262 * The meaning of `cause` that is passed to the handler:
Yanis Batura8140cfe2019-04-27 21:31:14 +0700263 * * Cause is `null` when the job has completed normally.
264 * * Cause is an instance of [CancellationException] when the job was cancelled _normally_.
Roman Elizarove89cd682018-04-25 13:03:40 +0300265 * **It should not be treated as an error**. In particular, it should not be reported to error logs.
266 * * Otherwise, the job had _failed_.
267 *
Roman Elizarove1c0b652017-12-01 14:02:57 +0300268 * The resulting [DisposableHandle] can be used to [dispose][DisposableHandle.dispose] the
269 * registration of this handler and release its memory if its invocation is no longer needed.
270 * There is no need to dispose the handler after completion of this job. The references to
271 * all the handlers are released when this job completes.
272 *
273 * Installed [handler] should not throw any exceptions. If it does, they will get caught,
274 * wrapped into [CompletionHandlerException], and rethrown, potentially causing crash of unrelated code.
275 *
Roman Elizarov2b8218a2019-04-11 01:41:22 +0300276 * **Note**: Implementation of `CompletionHandler` must be fast, non-blocking, and thread-safe.
277 * This handler can be invoked concurrently with the surrounding code.
278 * There is no guarantee on the execution context in which the [handler] is invoked.
Roman Elizarove1c0b652017-12-01 14:02:57 +0300279 */
280 public fun invokeOnCompletion(handler: CompletionHandler): DisposableHandle
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300281
Roman Elizarov29affbb2017-07-21 13:47:41 +0300282 /**
Roman Elizarov852fae52018-09-25 20:13:24 +0300283 * Registers handler that is **synchronously** invoked once on cancellation or completion of this job.
Yanis Batura8140cfe2019-04-27 21:31:14 +0700284 * when the job was already cancelled and is completed its execution, then the handler is immediately invoked
285 * with the job's cancellation cause or `null` unless [invokeImmediately] is set to false.
Roman Elizarov852fae52018-09-25 20:13:24 +0300286 * Otherwise, handler will be invoked once when this job is cancelled or is complete.
Roman Elizarov29affbb2017-07-21 13:47:41 +0300287 *
Roman Elizarove89cd682018-04-25 13:03:40 +0300288 * The meaning of `cause` that is passed to the handler:
Yanis Batura8140cfe2019-04-27 21:31:14 +0700289 * * Cause is `null` when the job has completed normally.
290 * * Cause is an instance of [CancellationException] when the job was cancelled _normally_.
Roman Elizarove89cd682018-04-25 13:03:40 +0300291 * **It should not be treated as an error**. In particular, it should not be reported to error logs.
292 * * Otherwise, the job had _failed_.
293 *
Roman Elizarov852fae52018-09-25 20:13:24 +0300294 * Invocation of this handler on a transition to a _cancelling_ state
Roman Elizarov6685fd02018-09-25 13:23:53 +0300295 * is controlled by [onCancelling] boolean parameter.
Roman Elizarov852fae52018-09-25 20:13:24 +0300296 * The handler is invoked when the job becomes _cancelling_ if [onCancelling] parameter is set to `true`.
Roman Elizarovd82b3a92017-06-23 21:52:08 +0300297 *
298 * The resulting [DisposableHandle] can be used to [dispose][DisposableHandle.dispose] the
299 * registration of this handler and release its memory if its invocation is no longer needed.
300 * There is no need to dispose the handler after completion of this job. The references to
301 * all the handlers are released when this job completes.
302 *
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300303 * Installed [handler] should not throw any exceptions. If it does, they will get caught,
304 * wrapped into [CompletionHandlerException], and rethrown, potentially causing crash of unrelated code.
305 *
Roman Elizarovd82b3a92017-06-23 21:52:08 +0300306 * **Note**: This function is a part of internal machinery that supports parent-child hierarchies
307 * and allows for implementation of suspending functions that wait on the Job's state.
308 * This function should not be used in general application code.
Roman Elizarov2b8218a2019-04-11 01:41:22 +0300309 * Implementation of `CompletionHandler` must be fast, non-blocking, and thread-safe.
310 * This handler can be invoked concurrently with the surrounding code.
311 * There is no guarantee on the execution context in which the [handler] is invoked.
Roman Elizarove1c0b652017-12-01 14:02:57 +0300312 *
Roman Elizarov852fae52018-09-25 20:13:24 +0300313 * @param onCancelling when `true`, then the [handler] is invoked as soon as this job transitions to _cancelling_ state;
Roman Elizarove1c0b652017-12-01 14:02:57 +0300314 * when `false` then the [handler] is invoked only when it transitions to _completed_ state.
Roman Elizarov6685fd02018-09-25 13:23:53 +0300315 * @param invokeImmediately when `true` and this job is already in the desired state (depending on [onCancelling]),
Vsevolod Tolstopyatov149ba482018-09-24 20:28:02 +0300316 * then the [handler] is immediately and synchronously invoked and no-op [DisposableHandle] is returned;
317 * when `false` then no-op [DisposableHandle] is returned, but the [handler] is not invoked.
Roman Elizarove1c0b652017-12-01 14:02:57 +0300318 * @param handler the handler.
Roman Elizarov1e0a2f02018-09-25 16:10:26 +0300319 *
Roman Elizarov27b8f452018-09-20 21:23:41 +0300320 * @suppress **This an internal API and should not be used from general code.**
Roman Elizarovd82b3a92017-06-23 21:52:08 +0300321 */
Roman Elizarov27b8f452018-09-20 21:23:41 +0300322 @InternalCoroutinesApi
Roman Elizarovaa461cf2018-04-11 13:20:29 +0300323 public fun invokeOnCompletion(
Roman Elizarov6685fd02018-09-25 13:23:53 +0300324 onCancelling: Boolean = false,
Roman Elizarove1c0b652017-12-01 14:02:57 +0300325 invokeImmediately: Boolean = true,
326 handler: CompletionHandler): DisposableHandle
Roman Elizarovd82b3a92017-06-23 21:52:08 +0300327
328 // ------------ unstable internal API ------------
329
330 /**
Roman Elizarovfc7a9a22017-02-13 11:54:01 +0300331 * @suppress **Error**: Operator '+' on two Job objects is meaningless.
Roman Elizarov32d95322017-02-09 15:57:31 +0300332 * Job is a coroutine context element and `+` is a set-sum operator for coroutine contexts.
333 * The job to the right of `+` just replaces the job the left of `+`.
334 */
Roman Elizarov79a28682017-02-01 18:43:32 +0300335 @Suppress("DeprecatedCallableAddReplaceWith")
336 @Deprecated(message = "Operator '+' on two Job objects is meaningless. " +
Roman Elizarovaa461cf2018-04-11 13:20:29 +0300337 "Job is a coroutine context element and `+` is a set-sum operator for coroutine contexts. " +
338 "The job to the right of `+` just replaces the job the left of `+`.",
339 level = DeprecationLevel.ERROR)
Roman Elizarov79a28682017-02-01 18:43:32 +0300340 public operator fun plus(other: Job) = other
Roman Elizarov3754f952017-01-18 20:47:54 +0300341}
342
Roman Elizarov32d95322017-02-09 15:57:31 +0300343/**
Inego564a5a62019-04-21 14:34:55 +0700344 * Creates a job object in an active state.
Roman Elizarov21f171c2018-09-23 19:16:04 +0300345 * A failure of any child of this job immediately causes this job to fail, too, and cancels the rest of its children.
346 *
347 * To handle children failure independently of each other use [SupervisorJob].
348 *
349 * If [parent] job is specified, then this job becomes a child job of its parent and
350 * is cancelled when its parent fails or is cancelled. All this job's children are cancelled in this case, too.
351 * The invocation of [cancel][Job.cancel] with exception (other than [CancellationException]) on this job also cancels parent.
352 *
Roman Elizarovcd2a8d72019-02-12 15:17:17 +0300353 * Conceptually, the resulting job works in the same way as the job created by the `launch { body }` invocation
354 * (see [launch]), but without any code in the body. It is active until cancelled or completed. Invocation of
355 * [CompletableJob.complete] or [CompletableJob.completeExceptionally] corresponds to the successful or
356 * failed completion of the body of the coroutine.
357 *
Roman Elizarov21f171c2018-09-23 19:16:04 +0300358 * @param parent an optional parent job.
Roman Elizaroveb6bf842017-07-21 18:10:22 +0300359 */
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300360@Suppress("FunctionName")
Roman Elizarovcd2a8d72019-02-12 15:17:17 +0300361public fun Job(parent: Job? = null): CompletableJob = JobImpl(parent)
362
363/** @suppress Binary compatibility only */
364@Suppress("FunctionName")
Roman Elizarov73b456b2019-03-06 17:18:27 +0300365@Deprecated(level = DeprecationLevel.HIDDEN, message = "Since 1.2.0, binary compatibility with versions <= 1.1.x")
Roman Elizarovcd2a8d72019-02-12 15:17:17 +0300366@JvmName("Job")
367public fun Job0(parent: Job? = null): Job = Job(parent)
Roman Elizaroveb6bf842017-07-21 18:10:22 +0300368
369/**
Roman Elizarovdaa1d9d2017-03-02 19:00:50 +0300370 * A handle to an allocated object that can be disposed to make it eligible for garbage collection.
371 */
Roman Elizarovaa461cf2018-04-11 13:20:29 +0300372public interface DisposableHandle {
Roman Elizarovdaa1d9d2017-03-02 19:00:50 +0300373 /**
374 * Disposes the corresponding object, making it eligible for garbage collection.
375 * Repeated invocation of this function has no effect.
376 */
Roman Elizarovaa461cf2018-04-11 13:20:29 +0300377 public fun dispose()
Roman Elizarovdaa1d9d2017-03-02 19:00:50 +0300378}
379
Roman Elizarov5d18d022018-09-22 22:13:05 +0300380/**
Roman Elizarov27b8f452018-09-20 21:23:41 +0300381 * @suppress **This an internal API and should not be used from general code.**
382 */
383@Suppress("FunctionName")
384@InternalCoroutinesApi
385public inline fun DisposableHandle(crossinline block: () -> Unit) =
386 object : DisposableHandle {
387 override fun dispose() {
388 block()
389 }
390 }
391
Roman Elizarov1e0a2f02018-09-25 16:10:26 +0300392// -------------------- Parent-child communication --------------------
393
394/**
Roman Elizarov852fae52018-09-25 20:13:24 +0300395 * A reference that parent receives from its child so that it can report its cancellation.
Roman Elizarovf7a63342018-09-25 00:26:25 +0300396 *
Roman Elizarov5d18d022018-09-22 22:13:05 +0300397 * @suppress **This is unstable API and it is subject to change.**
398 */
Vsevolod Tolstopyatovb5d10d42018-09-28 16:28:16 +0300399@InternalCoroutinesApi
Vsevolod Tolstopyatov7fb590d2018-10-11 18:22:46 +0300400@Deprecated(level = DeprecationLevel.ERROR, message = "This is internal API and may be removed in the future releases")
401public interface ChildJob : Job {
Roman Elizarovf7a63342018-09-25 00:26:25 +0300402 /**
Roman Elizarov852fae52018-09-25 20:13:24 +0300403 * Parent is cancelling its child by invoking this method.
Roman Elizarovb5c9c9f2018-09-29 13:16:47 +0300404 * Child finds the cancellation cause using [ParentJob.getChildJobCancellationCause].
Roman Elizarov852fae52018-09-25 20:13:24 +0300405 * This method does nothing is the child is already being cancelled.
Roman Elizarovf7a63342018-09-25 00:26:25 +0300406 *
407 * @suppress **This is unstable API and it is subject to change.**
408 */
Vsevolod Tolstopyatovb5d10d42018-09-28 16:28:16 +0300409 @InternalCoroutinesApi
Roman Elizarovb5c9c9f2018-09-29 13:16:47 +0300410 public fun parentCancelled(parentJob: ParentJob)
411}
412
413/**
414 * A reference that child receives from its parent when it is being cancelled by the parent.
415 *
416 * @suppress **This is unstable API and it is subject to change.**
417 */
418@InternalCoroutinesApi
Vsevolod Tolstopyatov7fb590d2018-10-11 18:22:46 +0300419@Deprecated(level = DeprecationLevel.ERROR, message = "This is internal API and may be removed in the future releases")
420public interface ParentJob : Job {
Roman Elizarovb5c9c9f2018-09-29 13:16:47 +0300421 /**
422 * Child job is using this method to learn its cancellation cause when the parent cancels it with [ChildJob.parentCancelled].
423 * This method is invoked only if the child was not already being cancelled.
424 *
425 * @suppress **This is unstable API and it is subject to change.**
426 */
427 @InternalCoroutinesApi
428 public fun getChildJobCancellationCause(): Throwable
Roman Elizarovf7a63342018-09-25 00:26:25 +0300429}
430
431/**
Roman Elizarov852fae52018-09-25 20:13:24 +0300432 * A handle that child keep onto its parent so that it is able to report its cancellation.
Roman Elizarov1e0a2f02018-09-25 16:10:26 +0300433 *
Roman Elizarovf7a63342018-09-25 00:26:25 +0300434 * @suppress **This is unstable API and it is subject to change.**
435 */
Vsevolod Tolstopyatovb5d10d42018-09-28 16:28:16 +0300436@InternalCoroutinesApi
Vsevolod Tolstopyatov7fb590d2018-10-11 18:22:46 +0300437@Deprecated(level = DeprecationLevel.ERROR, message = "This is internal API and may be removed in the future releases")
438public interface ChildHandle : DisposableHandle {
Roman Elizarov5d18d022018-09-22 22:13:05 +0300439 /**
Roman Elizarov852fae52018-09-25 20:13:24 +0300440 * Child is cancelling its parent by invoking this method.
Roman Elizarov5d18d022018-09-22 22:13:05 +0300441 * This method is invoked by the child twice. The first time child report its root cause as soon as possible,
Roman Elizarov852fae52018-09-25 20:13:24 +0300442 * so that all its siblings and the parent can start cancelling their work asap. The second time
443 * child invokes this method when it had aggregated and determined its final cancellation cause.
Roman Elizarov5d18d022018-09-22 22:13:05 +0300444 *
445 * @suppress **This is unstable API and it is subject to change.**
446 */
Vsevolod Tolstopyatovb5d10d42018-09-28 16:28:16 +0300447 @InternalCoroutinesApi
Roman Elizarov6685fd02018-09-25 13:23:53 +0300448 public fun childCancelled(cause: Throwable): Boolean
Roman Elizarov5d18d022018-09-22 22:13:05 +0300449}
450
Roman Elizarov3e387b82017-12-04 13:49:11 +0300451// -------------------- Job extensions --------------------
452
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300453/**
Roman Elizarovdaa1d9d2017-03-02 19:00:50 +0300454 * Disposes a specified [handle] when this job is complete.
455 *
456 * This is a shortcut for the following code with slightly more efficient implementation (one fewer object created).
457 * ```
458 * invokeOnCompletion { handle.dispose() }
459 * ```
460 */
Vsevolod Tolstopyatov1f7b2d82018-10-09 15:57:51 +0300461internal fun Job.disposeOnCompletion(handle: DisposableHandle): DisposableHandle =
Roman Elizarovaa461cf2018-04-11 13:20:29 +0300462 invokeOnCompletion(handler = DisposeOnCompletion(this, handle).asHandler)
Roman Elizarov3754f952017-01-18 20:47:54 +0300463
Roman Elizarovf0246082017-02-10 18:02:38 +0300464/**
Inego596187e2019-04-21 14:21:53 +0700465 * Cancels the job and suspends the invoking coroutine until the cancelled job is complete.
Roman Elizarov44ba5d02017-09-06 15:45:24 +0300466 *
Inego596187e2019-04-21 14:21:53 +0700467 * This suspending function is cancellable and **always** checks for a cancellation of the invoking coroutine's Job.
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300468 * If the [Job] of the invoking coroutine is cancelled or completed when this
469 * suspending function is invoked or while it is suspended, this function
470 * throws [CancellationException].
471 *
472 * In particular, it means that a parent coroutine invoking `cancelAndJoin` on a child coroutine that was started using
473 * `launch(coroutineContext) { ... }` builder throws [CancellationException] if the child
paolop81c75212018-06-02 10:03:33 +0000474 * had crashed, unless a non-standard [CoroutineExceptionHandler] is installed in the context.
Roman Elizarov44ba5d02017-09-06 15:45:24 +0300475 *
476 * This is a shortcut for the invocation of [cancel][Job.cancel] followed by [join][Job.join].
477 */
Roman Elizarovaa461cf2018-04-11 13:20:29 +0300478public suspend fun Job.cancelAndJoin() {
Roman Elizarov44ba5d02017-09-06 15:45:24 +0300479 cancel()
480 return join()
481}
482
483/**
Roman Elizarov0aad8f12019-03-01 12:08:43 +0300484 * Cancels all [children][Job.children] jobs of this coroutine using [Job.cancel] for all of them
485 * with an optional cancellation [cause].
486 * Unlike [Job.cancel] on this job as a whole, the state of this job itself is not affected.
Roman Elizarov3e387b82017-12-04 13:49:11 +0300487 */
Roman Elizarov0aad8f12019-03-01 12:08:43 +0300488public fun Job.cancelChildren(cause: CancellationException? = null) {
Roman Elizarov3e387b82017-12-04 13:49:11 +0300489 children.forEach { it.cancel(cause) }
490}
491
Vsevolod Tolstopyatovb058ba12018-10-17 15:15:17 +0300492/**
Roman Elizarov0aad8f12019-03-01 12:08:43 +0300493 * @suppress This method implements old version of JVM ABI. Use [cancel].
Vsevolod Tolstopyatovb058ba12018-10-17 15:15:17 +0300494 */
Roman Elizarov73b456b2019-03-06 17:18:27 +0300495@Deprecated(level = DeprecationLevel.HIDDEN, message = "Since 1.2.0, binary compatibility with versions <= 1.1.x")
Roman Elizarov0aad8f12019-03-01 12:08:43 +0300496public fun Job.cancelChildren() = cancelChildren(null)
497
498/**
499 * @suppress This method has bad semantics when cause is not a [CancellationException]. Use [Job.cancelChildren].
500 */
Roman Elizarov73b456b2019-03-06 17:18:27 +0300501@Deprecated(level = DeprecationLevel.HIDDEN, message = "Since 1.2.0, binary compatibility with versions <= 1.1.x")
Roman Elizarov0aad8f12019-03-01 12:08:43 +0300502public fun Job.cancelChildren(cause: Throwable? = null) {
503 children.forEach { (it as? JobSupport)?.cancelInternal(cause) }
Vsevolod Tolstopyatovb058ba12018-10-17 15:15:17 +0300504}
505
Roman Elizarov3e387b82017-12-04 13:49:11 +0300506// -------------------- CoroutineContext extensions --------------------
507
508/**
Roman Elizarov9fe5f462018-02-21 19:05:52 +0300509 * Returns `true` when the [Job] of the coroutine in this context is still active
510 * (has not completed and was not cancelled yet).
511 *
512 * Check this property in long-running computation loops to support cancellation
513 * when [CoroutineScope.isActive] is not available:
514 *
515 * ```
516 * while (coroutineContext.isActive) {
517 * // do some computation
518 * }
519 * ```
520 *
521 * The `coroutineContext.isActive` expression is a shortcut for `coroutineContext[Job]?.isActive == true`.
522 * See [Job.isActive].
523 */
Roman Elizarovaa461cf2018-04-11 13:20:29 +0300524public val CoroutineContext.isActive: Boolean
Roman Elizarov9fe5f462018-02-21 19:05:52 +0300525 get() = this[Job]?.isActive == true
526
Roman Elizarov27b8f452018-09-20 21:23:41 +0300527/**
Roman Elizarov0aad8f12019-03-01 12:08:43 +0300528 * Cancels [Job] of this context with an optional cancellation cause.
529 * See [Job.cancel] for details.
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300530 */
Roman Elizarov0aad8f12019-03-01 12:08:43 +0300531public fun CoroutineContext.cancel(cause: CancellationException? = null) {
532 this[Job]?.cancel(cause)
Vsevolod Tolstopyatovb058ba12018-10-17 15:15:17 +0300533}
534
535/**
Roman Elizarov0aad8f12019-03-01 12:08:43 +0300536 * @suppress This method implements old version of JVM ABI. Use [CoroutineContext.cancel].
Vsevolod Tolstopyatovb058ba12018-10-17 15:15:17 +0300537 */
Roman Elizarov73b456b2019-03-06 17:18:27 +0300538@Deprecated(level = DeprecationLevel.HIDDEN, message = "Since 1.2.0, binary compatibility with versions <= 1.1.x")
Roman Elizarov0aad8f12019-03-01 12:08:43 +0300539public fun CoroutineContext.cancel() = cancel(null)
Vsevolod Tolstopyatovb058ba12018-10-17 15:15:17 +0300540
541/**
Vsevolod Tolstopyatov5ae39472019-03-01 15:56:57 +0300542 * Ensures that current job is [active][Job.isActive].
543 * If the job is no longer active, throws [CancellationException].
544 * If the job was cancelled, thrown exception contains the original cancellation cause.
545 *
546 * This method is a drop-in replacement for the following code, but with more precise exception:
547 * ```
548 * if (!job.isActive) {
549 * throw CancellationException()
550 * }
551 * ```
552 */
553public fun Job.ensureActive(): Unit {
554 if (!isActive) throw getCancellationException()
555}
556
557/**
558 * Ensures that job in the current context is [active][Job.isActive].
559 * Throws [IllegalStateException] if the context does not have a job in it.
560 *
561 * If the job is no longer active, throws [CancellationException].
562 * If the job was cancelled, thrown exception contains the original cancellation cause.
563 *
564 * This method is a drop-in replacement for the following code, but with more precise exception:
565 * ```
566 * if (!isActive) {
567 * throw CancellationException()
568 * }
569 * ```
570 */
571public fun CoroutineContext.ensureActive(): Unit {
572 val job = get(Job) ?: error("Context cannot be checked for liveness because it does not have a job: $this")
573 job.ensureActive()
574}
575
576/**
Roman Elizarov0aad8f12019-03-01 12:08:43 +0300577 * @suppress This method has bad semantics when cause is not a [CancellationException]. Use [CoroutineContext.cancel].
Vsevolod Tolstopyatovb058ba12018-10-17 15:15:17 +0300578 */
Roman Elizarov73b456b2019-03-06 17:18:27 +0300579@Deprecated(level = DeprecationLevel.HIDDEN, message = "Since 1.2.0, binary compatibility with versions <= 1.1.x")
Roman Elizarovaa461cf2018-04-11 13:20:29 +0300580public fun CoroutineContext.cancel(cause: Throwable? = null): Boolean =
Vsevolod Tolstopyatov6b2e90b2018-11-12 15:30:45 +0300581 @Suppress("DEPRECATION")
Roman Elizarov0aad8f12019-03-01 12:08:43 +0300582 (this[Job] as? JobSupport)?.cancelInternal(cause) ?: false
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300583
584/**
Vitus34287742019-05-03 22:23:03 +0200585 * Cancels all children of the [Job] in this context, without touching the state of this job itself
Roman Elizarov0aad8f12019-03-01 12:08:43 +0300586 * with an optional cancellation cause. See [Job.cancel].
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300587 * It does not do anything if there is no job in the context or it has no children.
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300588 */
Roman Elizarov0aad8f12019-03-01 12:08:43 +0300589public fun CoroutineContext.cancelChildren(cause: CancellationException? = null) {
590 this[Job]?.children?.forEach { it.cancel(cause) }
Roman Elizarov27b8f452018-09-20 21:23:41 +0300591}
592
Roman Elizarov0aad8f12019-03-01 12:08:43 +0300593/**
594 * @suppress This method implements old version of JVM ABI. Use [CoroutineContext.cancelChildren].
595 */
Roman Elizarov73b456b2019-03-06 17:18:27 +0300596@Deprecated(level = DeprecationLevel.HIDDEN, message = "Since 1.2.0, binary compatibility with versions <= 1.1.x")
Roman Elizarov0aad8f12019-03-01 12:08:43 +0300597public fun CoroutineContext.cancelChildren() = cancelChildren(null)
598
599/**
600 * @suppress This method has bad semantics when cause is not a [CancellationException]. Use [CoroutineContext.cancelChildren].
601 */
Roman Elizarov73b456b2019-03-06 17:18:27 +0300602@Deprecated(level = DeprecationLevel.HIDDEN, message = "Since 1.2.0, binary compatibility with versions <= 1.1.x")
Roman Elizarovaa461cf2018-04-11 13:20:29 +0300603public fun CoroutineContext.cancelChildren(cause: Throwable? = null) {
Roman Elizarov0aad8f12019-03-01 12:08:43 +0300604 this[Job]?.children?.forEach { (it as? JobSupport)?.cancelInternal(cause) }
Roman Elizarov8b38fa22017-09-27 17:44:31 +0300605}
606
607/**
Roman Elizarovdaa1d9d2017-03-02 19:00:50 +0300608 * No-op implementation of [DisposableHandle].
Roman Elizarov27b8f452018-09-20 21:23:41 +0300609 * @suppress **This an internal API and should not be used from general code.**
Roman Elizarovdaa1d9d2017-03-02 19:00:50 +0300610 */
Vsevolod Tolstopyatov149ba482018-09-24 20:28:02 +0300611@InternalCoroutinesApi
Roman Elizarov5d18d022018-09-22 22:13:05 +0300612public object NonDisposableHandle : DisposableHandle, ChildHandle {
613 /**
614 * Does not do anything.
615 * @suppress
616 */
Roman Elizarovaa461cf2018-04-11 13:20:29 +0300617 override fun dispose() {}
Roman Elizarovdaa1d9d2017-03-02 19:00:50 +0300618
Roman Elizarov5d18d022018-09-22 22:13:05 +0300619 /**
620 * Returns `false`.
621 * @suppress
622 */
Roman Elizarov6685fd02018-09-25 13:23:53 +0300623 override fun childCancelled(cause: Throwable): Boolean = false
Roman Elizarov5d18d022018-09-22 22:13:05 +0300624
625 /**
626 * Returns "NonDisposableHandle" string.
627 * @suppress
628 */
Roman Elizarovdaa1d9d2017-03-02 19:00:50 +0300629 override fun toString(): String = "NonDisposableHandle"
Roman Elizarov3754f952017-01-18 20:47:54 +0300630}