Skip to content

Commit 92df6e1

Browse files
committed
Reword the prompt cancellation guarantee
Emphasize the fact that the function fails to resume *even if it already completed* but wasn't dispatched yet. Before the change, when translating the documentation to Chinese, there could be a confusion as to what "it will not resume successfully" means. Fixes #3888
1 parent 8eb4963 commit 92df6e1

File tree

12 files changed

+101
-96
lines changed

12 files changed

+101
-96
lines changed

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

+16-20
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,10 @@ import kotlin.coroutines.*
1111
* This function is **not** equivalent to `deferreds.map { it.await() }` which fails only when it sequentially
1212
* gets to wait for the failing deferred, while this `awaitAll` fails immediately as soon as any of the deferreds fail.
1313
*
14-
* This suspending function is cancellable.
15-
* If the [Job] of the current coroutine is cancelled or completed while this suspending function is waiting,
16-
* this function immediately resumes with [CancellationException].
17-
* There is a **prompt cancellation guarantee**. If the job was cancelled while this function was
18-
* suspended, it will not resume successfully. See [suspendCancellableCoroutine] documentation for low-level details.
14+
* This suspending function is cancellable: if the [Job] of the current coroutine is cancelled or completed while this
15+
* suspending function is waiting, this function immediately resumes with [CancellationException].
16+
* There is a **prompt cancellation guarantee**: even if this function is ready to return the result, but was cancelled
17+
* while suspended, [CancellationException] will be thrown. See [suspendCancellableCoroutine] for low-level details.
1918
*/
2019
public suspend fun <T> awaitAll(vararg deferreds: Deferred<T>): List<T> =
2120
if (deferreds.isEmpty()) emptyList() else AwaitAll(deferreds).await()
@@ -28,11 +27,10 @@ public suspend fun <T> awaitAll(vararg deferreds: Deferred<T>): List<T> =
2827
* This function is **not** equivalent to `this.map { it.await() }` which fails only when it sequentially
2928
* gets to wait for the failing deferred, while this `awaitAll` fails immediately as soon as any of the deferreds fail.
3029
*
31-
* This suspending function is cancellable.
32-
* If the [Job] of the current coroutine is cancelled or completed while this suspending function is waiting,
33-
* this function immediately resumes with [CancellationException].
34-
* There is a **prompt cancellation guarantee**. If the job was cancelled while this function was
35-
* suspended, it will not resume successfully. See [suspendCancellableCoroutine] documentation for low-level details.
30+
* This suspending function is cancellable: if the [Job] of the current coroutine is cancelled or completed while this
31+
* suspending function is waiting, this function immediately resumes with [CancellationException].
32+
* There is a **prompt cancellation guarantee**: even if this function is ready to return the result, but was cancelled
33+
* while suspended, [CancellationException] will be thrown. See [suspendCancellableCoroutine] for low-level details.
3634
*/
3735
public suspend fun <T> Collection<Deferred<T>>.awaitAll(): List<T> =
3836
if (isEmpty()) emptyList() else AwaitAll(toTypedArray()).await()
@@ -41,23 +39,21 @@ public suspend fun <T> Collection<Deferred<T>>.awaitAll(): List<T> =
4139
* Suspends current coroutine until all given jobs are complete.
4240
* This method is semantically equivalent to joining all given jobs one by one with `jobs.forEach { it.join() }`.
4341
*
44-
* This suspending function is cancellable.
45-
* If the [Job] of the current coroutine is cancelled or completed while this suspending function is waiting,
46-
* this function immediately resumes with [CancellationException].
47-
* There is a **prompt cancellation guarantee**. If the job was cancelled while this function was
48-
* suspended, it will not resume successfully. See [suspendCancellableCoroutine] documentation for low-level details.
42+
* This suspending function is cancellable: if the [Job] of the current coroutine is cancelled or completed while this
43+
* suspending function is waiting, this function immediately resumes with [CancellationException].
44+
* There is a **prompt cancellation guarantee**: even if this function is ready to return the result, but was cancelled
45+
* while suspended, [CancellationException] will be thrown. See [suspendCancellableCoroutine] for low-level details.
4946
*/
5047
public suspend fun joinAll(vararg jobs: Job): Unit = jobs.forEach { it.join() }
5148

5249
/**
5350
* Suspends current coroutine until all given jobs are complete.
5451
* This method is semantically equivalent to joining all given jobs one by one with `forEach { it.join() }`.
5552
*
56-
* This suspending function is cancellable.
57-
* If the [Job] of the current coroutine is cancelled or completed while this suspending function is waiting,
58-
* this function immediately resumes with [CancellationException].
59-
* There is a **prompt cancellation guarantee**. If the job was cancelled while this function was
60-
* suspended, it will not resume successfully. See [suspendCancellableCoroutine] documentation for low-level details.
53+
* This suspending function is cancellable: if the [Job] of the current coroutine is cancelled or completed while this
54+
* suspending function is waiting, this function immediately resumes with [CancellationException].
55+
* There is a **prompt cancellation guarantee**: even if this function is ready to return the result, but was cancelled
56+
* while suspended, [CancellationException] will be thrown. See [suspendCancellableCoroutine] for low-level details.
6157
*/
6258
public suspend fun Collection<Job>.joinAll(): Unit = forEach { it.join() }
6359

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

+9-9
Original file line numberDiff line numberDiff line change
@@ -238,25 +238,25 @@ public interface CancellableContinuation<in T> : Continuation<T> {
238238
*
239239
* This function provides **prompt cancellation guarantee**.
240240
* If the [Job] of the current coroutine was cancelled while this function was suspended it will not resume
241-
* successfully.
241+
* successfully, even if [CancellableContinuation.resume] was already invoked.
242242
*
243243
* The cancellation of the coroutine's job is generally asynchronous with respect to the suspended coroutine.
244-
* The suspended coroutine is resumed with the call it to its [Continuation.resumeWith] member function or to
244+
* The suspended coroutine is resumed with a call to its [Continuation.resumeWith] member function or to the
245245
* [resume][Continuation.resume] extension function.
246246
* However, when coroutine is resumed, it does not immediately start executing, but is passed to its
247247
* [CoroutineDispatcher] to schedule its execution when dispatcher's resources become available for execution.
248-
* The job's cancellation can happen both before, after, and concurrently with the call to `resume`. In any
249-
* case, prompt cancellation guarantees that the the coroutine will not resume its code successfully.
248+
* The job's cancellation can happen before, after, and concurrently with the call to `resume`. In any
249+
* case, prompt cancellation guarantees that the coroutine will not resume its code successfully.
250250
*
251251
* If the coroutine was resumed with an exception (for example, using [Continuation.resumeWithException] extension
252-
* function) and cancelled, then the resulting exception of the `suspendCancellableCoroutine` function is determined
253-
* by whichever action (exceptional resume or cancellation) that happened first.
252+
* function) and cancelled, then the exception thrown by the `suspendCancellableCoroutine` function is determined
253+
* by what happened first: exceptional resume or cancellation.
254254
*
255255
* ### Returning resources from a suspended coroutine
256256
*
257-
* As a result of a prompt cancellation guarantee, when a closeable resource
258-
* (like open file or a handle to another native resource) is returned from a suspended coroutine as a value
259-
* it can be lost when the coroutine is cancelled. In order to ensure that the resource can be properly closed
257+
* As a result of the prompt cancellation guarantee, when a closeable resource
258+
* (like open file or a handle to another native resource) is returned from a suspended coroutine as a value,
259+
* it can be lost when the coroutine is cancelled. To ensure that the resource can be properly closed
260260
* in this case, the [CancellableContinuation] interface provides two functions.
261261
*
262262
* - [invokeOnCancellation][CancellableContinuation.invokeOnCancellation] installs a handler that is called

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,8 @@ public interface Deferred<out T> : Job {
5858
* }
5959
* ```
6060
*
61-
* There is a **prompt cancellation guarantee**. If the job was cancelled while this function was
62-
* suspended, it will not resume successfully. See [suspendCancellableCoroutine] documentation for low-level details.
61+
* There is a **prompt cancellation guarantee**: even if this function is ready to return the result, but was cancelled
62+
* while suspended, [CancellationException] will be thrown. See [suspendCancellableCoroutine] for low-level details.
6363
*
6464
* This function can be used in [select] invocations with an [onAwait] clause.
6565
* Use [isCompleted] to check for completion of this deferred value without waiting, and

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

+8-10
Original file line numberDiff line numberDiff line change
@@ -106,11 +106,10 @@ public suspend fun awaitCancellation(): Nothing = suspendCancellableCoroutine {}
106106
* Delays coroutine for at least the given time without blocking a thread and resumes it after a specified time.
107107
* If the given [timeMillis] is non-positive, this function returns immediately.
108108
*
109-
* This suspending function is cancellable.
110-
* If the [Job] of the current coroutine is cancelled or completed while this suspending function is waiting, this function
111-
* immediately resumes with [CancellationException].
112-
* There is a **prompt cancellation guarantee**. If the job was cancelled while this function was
113-
* suspended, it will not resume successfully. See [suspendCancellableCoroutine] documentation for low-level details.
109+
* This suspending function is cancellable: if the [Job] of the current coroutine is cancelled or completed while this
110+
* suspending function is waiting, this function immediately resumes with [CancellationException].
111+
* There is a **prompt cancellation guarantee**: even if this function is ready to return the result, but was cancelled
112+
* while suspended, [CancellationException] will be thrown. See [suspendCancellableCoroutine] for low-level details.
114113
*
115114
* If you want to delay forever (until cancellation), consider using [awaitCancellation] instead.
116115
*
@@ -133,11 +132,10 @@ public suspend fun delay(timeMillis: Long) {
133132
* Delays coroutine for at least the given [duration] without blocking a thread and resumes it after the specified time.
134133
* If the given [duration] is non-positive, this function returns immediately.
135134
*
136-
* This suspending function is cancellable.
137-
* If the [Job] of the current coroutine is cancelled or completed while this suspending function is waiting, this function
138-
* immediately resumes with [CancellationException].
139-
* There is a **prompt cancellation guarantee**. If the job was cancelled while this function was
140-
* suspended, it will not resume successfully. See [suspendCancellableCoroutine] documentation for low-level details.
135+
* This suspending function is cancellable: if the [Job] of the current coroutine is cancelled or completed while this
136+
* suspending function is waiting, this function immediately resumes with [CancellationException].
137+
* There is a **prompt cancellation guarantee**: even if this function is ready to return the result, but was cancelled
138+
* while suspended, [CancellationException] will be thrown. See [suspendCancellableCoroutine] for low-level details.
141139
*
142140
* If you want to delay forever (until cancellation), consider using [awaitCancellation] instead.
143141
*

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

+5-6
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,11 @@ import kotlin.coroutines.intrinsics.*
66
/**
77
* Yields the thread (or thread pool) of the current coroutine dispatcher
88
* to other coroutines on the same dispatcher to run if possible.
9-
*
10-
* This suspending function is cancellable.
11-
* If the [Job] of the current coroutine is cancelled or completed when this suspending function is invoked or while
12-
* this function is waiting for dispatch, it resumes with a [CancellationException].
13-
* There is a **prompt cancellation guarantee**. If the job was cancelled while this function was
14-
* suspended, it will not resume successfully. See [suspendCancellableCoroutine] documentation for low-level details.
9+
*
10+
* This suspending function is cancellable: if the [Job] of the current coroutine is cancelled or completed while
11+
* [yield] is invoked or while waiting for dispatch, it immediately resumes with [CancellationException].
12+
* There is a **prompt cancellation guarantee**: even if this function is ready to return the result, but was cancelled
13+
* while suspended, [CancellationException] will be thrown. See [suspendCancellableCoroutine] for low-level details.
1514
*
1615
* **Note**: This function always [checks for cancellation][ensureActive] even when it does not suspend.
1716
*

0 commit comments

Comments
 (0)