@@ -34,6 +34,8 @@ import kotlin.jvm.*
3434 *
3535 * ## Structured Concurrency
3636 *
37+ * ### Coroutine context
38+ *
3739 * [launch] creates a *child coroutine* of `this` [CoroutineScope].
3840 *
3941 * The context of the new coroutine is created like this:
@@ -55,8 +57,10 @@ import kotlin.jvm.*
5557 * If the [block] throws a [CancellationException], the coroutine is considered cancelled,
5658 * and if it throws any other exception, the coroutine is considered failed.
5759 *
60+ * ### Interactions between coroutines
61+ *
5862 * The details of structured concurrency are described in the [CoroutineScope] interface documentation.
59- * Here is a restatement of some main points as they relate to ` launch` :
63+ * Here is a restatement of some main points as they relate to [ launch] :
6064 *
6165 * - The lifecycle of the parent [CoroutineScope] can not end until this coroutine
6266 * (as well as all its children) completes.
@@ -113,6 +117,16 @@ import kotlin.jvm.*
113117 * there is no reliable way to learn about that exception in general.
114118 * [async] is a better choice if the result of the coroutine needs to be accessed from another coroutine.
115119 *
120+ * ## Differences from [async]
121+ *
122+ * [launch] is similar to [async] whose block returns a [Unit] value.
123+ *
124+ * The only difference is the handling of uncaught coroutine exceptions:
125+ * if an [async] coroutine fails with an exception, then even if the exception can not be propagated to the parent,
126+ * a [CoroutineExceptionHandler] will not be invoked.
127+ * Instead, the user of [async] must call [Deferred.await] to get the result of the coroutine,
128+ * which will be the uncaught exception.
129+ *
116130 * ## Pitfalls
117131 *
118132 * ### [CancellationException] silently stopping computations
@@ -182,7 +196,7 @@ import kotlin.jvm.*
182196 *
183197 * @param context additional to [CoroutineScope.coroutineContext] context of the coroutine.
184198 * @param start coroutine start option. The default value is [CoroutineStart.DEFAULT].
185- * @param block the coroutine code which will be invoked in the context of the provided scope .
199+ * @param block the coroutine code which will be invoked in the child coroutine .
186200 **/
187201public fun CoroutineScope.launch (
188202 context : CoroutineContext = EmptyCoroutineContext ,
@@ -200,24 +214,73 @@ public fun CoroutineScope.launch(
200214// --------------- async ---------------
201215
202216/* *
203- * Creates a coroutine and returns its future result as an implementation of [Deferred].
204- * The running coroutine is cancelled when the resulting deferred is [cancelled][Job.cancel].
205- * The resulting coroutine has a key difference compared with similar primitives in other languages
206- * and frameworks: it cancels the parent job (or outer scope) on failure to enforce *structured concurrency* paradigm.
207- * To change that behaviour, supervising parent ([SupervisorJob] or [supervisorScope]) can be used.
208- *
209- * Coroutine context is inherited from a [CoroutineScope], additional context elements can be specified with [context] argument.
210- * If the context does not have any dispatcher nor any other [ContinuationInterceptor], then [Dispatchers.Default] is used.
211- * The parent job is inherited from a [CoroutineScope] as well, but it can also be overridden
212- * with corresponding [context] element.
213- *
214- * By default, the coroutine is immediately scheduled for execution.
215- * Other options can be specified via `start` parameter. See [CoroutineStart] for details.
216- * An optional [start] parameter can be set to [CoroutineStart.LAZY] to start coroutine _lazily_. In this case,
217- * the resulting [Deferred] is created in _new_ state. It can be explicitly started with [start][Job.start]
218- * function and will be started implicitly on the first invocation of [join][Job.join], [await][Deferred.await] or [awaitAll].
219- *
220- * @param block the coroutine code.
217+ * Launches a new *child coroutine* of [CoroutineScope] without blocking the current thread
218+ * and returns a reference to the coroutine as a [Deferred] that can be used to access the final value.
219+ *
220+ * [block] is the computation of the new coroutine that will run concurrently.
221+ * The coroutine is considered active until the block and all the child coroutines created in it finish.
222+ * The result of executing the [block] is available via the returned [Deferred].
223+ *
224+ * [context] specifies the additional context elements for the coroutine to combine with
225+ * the elements already present in the [CoroutineScope.coroutineContext].
226+ * It is incorrect to pass a [Job] element there, as this breaks structured concurrency.
227+ *
228+ * By default, the coroutine is scheduled for execution on its [ContinuationInterceptor].
229+ * There is no guarantee that it will start immediately: this is decided by the [ContinuationInterceptor].
230+ * It is possible that the new coroutine will be cancelled before starting, in which case its code will not be executed.
231+ * The [start] parameter can be used to adjust this behavior. See [CoroutineStart] for details.
232+ *
233+ * ## Structured Concurrency
234+ *
235+ * ### Coroutine context
236+ *
237+ * [async] creates a *child coroutine* of `this` [CoroutineScope].
238+ *
239+ * See the corresponding subsection in the [launch] documentation for details on how the coroutine context is created.
240+ * In essence, the elements of [context] are combined with the elements of the [CoroutineScope.coroutineContext],
241+ * typically overriding them. It is incorrect to pass a [Job] element there, as this breaks structured concurrency.
242+ *
243+ * ### Interactions between coroutines
244+ *
245+ * The details of structured concurrency are described in the [CoroutineScope] interface documentation.
246+ * Here is a restatement of some main points as they relate to [async]:
247+ *
248+ * - The lifecycle of the parent [CoroutineScope] can not end until this coroutine
249+ * (as well as all its children) completes.
250+ * - If the parent [CoroutineScope] is cancelled, this coroutine is cancelled as well.
251+ * - If this coroutine fails with a non-[CancellationException] exception
252+ * and the parent [CoroutineScope] has a non-supervisor [Job] in its context,
253+ * the parent [Job] is cancelled with this exception.
254+ * - If this coroutine fails with an exception and the parent [CoroutineScope] has a supervisor [Job] or no job at all
255+ * (as is the case with [GlobalScope] or malformed scopes),
256+ * the exception is considered uncaught and is only available through the returned [Deferred].
257+ * - The lifecycle of the [CoroutineScope] passed as the receiver to the [block]
258+ * will not end until the [block] completes (or gets cancelled before ever having a chance to run).
259+ * - If the [block] throws a [CancellationException], the coroutine is considered cancelled,
260+ * cancelling all its children in turn, but the parent does not get notified.
261+ *
262+ * ## Communicating with the coroutine
263+ *
264+ * [Deferred.await] can be used to suspend the current coroutine until the result of the [async] coroutine is available.
265+ * It returns the result of the [block] executed in the [async] coroutine.
266+ * Note that if the [async] coroutine fails with an exception, [Deferred.await] will also throw that exception,
267+ * including [CancellationException] if the coroutine was cancelled.
268+ * See the "CancellationException silently stopping computations" pitfall in the [launch] documentation.
269+ *
270+ * [Deferred.cancel] can be used to cancel the coroutine, and [Deferred.join] can be used to block until its completion
271+ * without blocking the current thread or accessing its result.
272+ * Note that [Deferred.join] succeeds even if the coroutine was cancelled or failed with an exception.
273+ * [Deferred.cancelAndJoin] is a convenience function that combines cancellation and joining.
274+ *
275+ * If the coroutine was started with [start] set to [CoroutineStart.LAZY], the coroutine will not be scheduled
276+ * to run on its [ContinuationInterceptor] immediately.
277+ * [Deferred.start] can be used to start the coroutine explicitly,
278+ * and awaiting its result using [Deferred.await] or [awaitAll] or its completion using [Deferred.join]
279+ * also causes the coroutine to start executing.
280+ *
281+ * @param context additional to [CoroutineScope.coroutineContext] context of the coroutine.
282+ * @param start coroutine start option. The default value is [CoroutineStart.DEFAULT].
283+ * @param block the coroutine code which will be invoked in the child coroutine.
221284 */
222285public fun <T > CoroutineScope.async (
223286 context : CoroutineContext = EmptyCoroutineContext ,
0 commit comments