Skip to content

Commit 7382bb3

Browse files
authored
Improved Job docs (#2035)
* A more consistent prose in the Job interface documentation, gradually explaining concepts without repetition. * Clear introduction and naming of "coroutine job" vs "completable job". * Explanation of what is a "cancellation cause" of Job and how that relates to CancellationException. * Added a note to all Job-derived interfaces that they are not safe for inheritance in 3rd party libraries. * Consistently copied a note on thread-safety to all job-derived interfaces.
1 parent 5a20585 commit 7382bb3

File tree

4 files changed

+61
-21
lines changed

4 files changed

+61
-21
lines changed

kotlinx-coroutines-core/common/src/CompletableDeferred.kt

+4-1
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,11 @@ import kotlinx.coroutines.selects.*
1616
*
1717
* An instance of completable deferred can be created by `CompletableDeferred()` function in _active_ state.
1818
*
19-
* All functions on this interface and on all interfaces derived from it are **thread-safe** and can
19+
* All functions on this interface are **thread-safe** and can
2020
* be safely invoked from concurrent coroutines without external synchronization.
21+
*
22+
* **`CompletableDeferred` interface is not stable for inheritance in 3rd party libraries**,
23+
* as new methods might be added to this interface in the future, but is stable for use.
2124
*/
2225
public interface CompletableDeferred<T> : Deferred<T> {
2326
/**

kotlinx-coroutines-core/common/src/CompletableJob.kt

+6
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ package kotlinx.coroutines
77
/**
88
* A job that can be completed using [complete()] function.
99
* It is returned by [Job()][Job] and [SupervisorJob()][SupervisorJob] constructor functions.
10+
*
11+
* All functions on this interface are **thread-safe** and can
12+
* be safely invoked from concurrent coroutines without external synchronization.
13+
*
14+
* **`CompletableJob` interface is not stable for inheritance in 3rd party libraries**,
15+
* as new methods might be added to this interface in the future, but is stable for use.
1016
*/
1117
public interface CompletableJob : Job {
1218
/**

kotlinx-coroutines-core/common/src/Deferred.kt

+3
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ import kotlinx.coroutines.selects.*
3030
*
3131
* All functions on this interface and on all interfaces derived from it are **thread-safe** and can
3232
* be safely invoked from concurrent coroutines without external synchronization.
33+
*
34+
* **`Deferred` interface and all its derived interfaces are not stable for inheritance in 3rd party libraries**,
35+
* as new methods might be added to this interface in the future, but is stable for use.
3336
*/
3437
public interface Deferred<out T> : Job {
3538

kotlinx-coroutines-core/common/src/Job.kt

+48-20
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,22 @@ import kotlin.jvm.*
1919
* culminates in its completion.
2020
*
2121
* Jobs can be arranged into parent-child hierarchies where cancellation
22-
* 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
24-
* can [cancel] its own children (including all their children recursively) without cancelling itself.
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].
2525
*
26-
* The most basic instances of [Job] are created with [launch][CoroutineScope.launch] coroutine builder or with a
27-
* `Job()` factory function. By default, a failure of any of the job's children leads to an immediate failure
28-
* of its parent and cancellation of the rest of its children. This behavior can be customized using [SupervisorJob].
26+
* The most basic instances of `Job` interface are created like this:
2927
*
30-
* Conceptually, an execution of the job does not produce a result value. Jobs are launched solely for their
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
3134
* side-effects. See [Deferred] interface for a job that produces a result.
3235
*
36+
* ### Job states
37+
*
3338
* A job has the following states:
3439
*
3540
* | **State** | [isActive] | [isCompleted] | [isCancelled] |
@@ -41,13 +46,23 @@ import kotlin.jvm.*
4146
* | _Cancelled_ (final state) | `false` | `true` | `true` |
4247
* | _Completed_ (final state) | `false` | `true` | `false` |
4348
*
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
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
4651
* [CoroutineStart.LAZY]. Such a job can be made _active_ by invoking [start] or [join].
4752
*
48-
* A job is _active_ while the coroutine is working. Failure of the job with exception makes it _cancelling_.
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_.
4957
* 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.
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.
5166
*
5267
* ```
5368
* wait children
@@ -67,19 +82,32 @@ import kotlin.jvm.*
6782
* [coroutineContext](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines/coroutine-context.html)
6883
* represents the coroutine itself.
6984
*
70-
* 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.
72-
* Note that _completing_ state is purely internal to the job. For an outside observer a _completing_ job is still
73-
* active, while internally it is waiting for its children.
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.
7496
*
75-
* 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.
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
80103
*
81104
* All functions on this interface and on all interfaces derived from it are **thread-safe** and can
82105
* 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.
83111
*/
84112
public interface Job : CoroutineContext.Element {
85113
/**

0 commit comments

Comments
 (0)