Skip to content

Commit 75e72cd

Browse files
Improve CoroutineScope extensions documentation (#4269)
Co-authored-by: Dmitry Khalanskiy <[email protected]>
1 parent 96cad1f commit 75e72cd

File tree

1 file changed

+51
-12
lines changed

1 file changed

+51
-12
lines changed

Diff for: kotlinx-coroutines-core/common/src/CoroutineScope.kt

+51-12
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,13 @@ public interface CoroutineScope {
8787
* Adds the specified coroutine context to this scope, overriding existing elements in the current
8888
* scope's context with the corresponding keys.
8989
*
90-
* This is a shorthand for `CoroutineScope(thisScope.coroutineContext + context)`.
90+
* This is a shorthand for `CoroutineScope(thisScope.coroutineContext + context)` and can be used as
91+
* a combinator with existing constructors:
92+
* ```
93+
* class MyActivity {
94+
* val uiScope = MainScope() + CoroutineName("MyActivity")
95+
* }
96+
* ```
9197
*/
9298
public operator fun CoroutineScope.plus(context: CoroutineContext): CoroutineScope =
9399
ContextScope(coroutineContext + context)
@@ -117,13 +123,30 @@ public fun MainScope(): CoroutineScope = ContextScope(SupervisorJob() + Dispatch
117123
/**
118124
* Returns `true` when the current [Job] is still active (has not completed and was not cancelled yet).
119125
*
120-
* Check this property in long-running computation loops to support cancellation:
126+
* Coroutine cancallation [is cooperative](https://kotlinlang.org/docs/cancellation-and-timeouts.html#cancellation-is-cooperative)
127+
* and normally, it's checked if a coroutine is cancelled when it *suspends*, for example,
128+
* when trying to read from a [channel][kotlinx.coroutines.channels.Channel] that is empty.
129+
*
130+
* Sometimes, a coroutine does not need to perform suspending operations, but still wants to be cooperative
131+
* and respect cancellation.
132+
*
133+
* The [isActive] property is inteded to be used for scenarios like this:
121134
* ```
122-
* while (isActive) {
123-
* // do some computation
135+
* val watchdogDispatcher = Dispatchers.IO.limitParallelism(1)
136+
* fun backgroundWork() {
137+
* println("Doing bookkeeping in the background in a non-suspending manner")
138+
* Thread.sleep(100L) // Sleep 100ms
139+
* }
140+
* // Part of some non-trivial CoroutineScope-confined lifecycle
141+
* launch(watchdogDispatcher) {
142+
* while (isActive) {
143+
* // Repetitively do some background work that is non-suspending
144+
* backgroundWork()
145+
* }
124146
* }
125147
* ```
126148
*
149+
* This function returns `true` if there is no [job][Job] in the scope's [coroutineContext][CoroutineScope.coroutineContext].
127150
* This property is a shortcut for `coroutineContext.isActive` in the scope when
128151
* [CoroutineScope] is available.
129152
* See [coroutineContext][kotlin.coroutines.coroutineContext],
@@ -292,24 +315,40 @@ public fun CoroutineScope.cancel(cause: CancellationException? = null) {
292315
public fun CoroutineScope.cancel(message: String, cause: Throwable? = null): Unit = cancel(CancellationException(message, cause))
293316

294317
/**
295-
* Ensures that current scope is [active][CoroutineScope.isActive].
318+
* Throws the [CancellationException] that was the scope's cancellation cause if the scope is no longer [active][CoroutineScope.isActive].
296319
*
297-
* If the job is no longer active, throws [CancellationException].
298-
* If the job was cancelled, thrown exception contains the original cancellation cause.
299-
* This function does not do anything if there is no [Job] in the scope's [coroutineContext][CoroutineScope.coroutineContext].
320+
* Coroutine cancallation [is cooperative](https://kotlinlang.org/docs/cancellation-and-timeouts.html#cancellation-is-cooperative)
321+
* and normally, it's checked if a coroutine is cancelled when it *suspends*, for example,
322+
* when trying to read from a [channel][kotlinx.coroutines.channels.Channel] that is empty.
323+
*
324+
* Sometimes, a coroutine does not need to perform suspending operations, but still wants to be cooperative
325+
* and respect cancellation.
300326
*
301-
* This method is a drop-in replacement for the following code, but with more precise exception:
327+
* [ensureActive] function is inteded to be used for these scenarios and immediately bubble up the cancellation exception:
302328
* ```
303-
* if (!isActive) {
304-
* throw CancellationException()
329+
* val watchdogDispatcher = Dispatchers.IO.limitParallelism(1)
330+
* fun backgroundWork() {
331+
* println("Doing bookkeeping in the background in a non-suspending manner")
332+
* Thread.sleep(100L) // Sleep 100ms
333+
* }
334+
* fun postBackgroundCleanup() = println("Doing something else")
335+
* // Part of some non-trivial CoroutineScope-confined lifecycle
336+
* launch(watchdogDispatcher) {
337+
* while (true) {
338+
* // Repeatatively do some background work that is non-suspending
339+
* backgroundWork()
340+
* ensureActive() // Bail out if the scope was cancelled
341+
* postBackgroundCleanup() // Won't be invoked if the scope was cancelled
342+
* }
305343
* }
306344
* ```
345+
* This function does not do anything if there is no [Job] in the scope's [coroutineContext][CoroutineScope.coroutineContext].
307346
*
347+
* @see CoroutineScope.isActive
308348
* @see CoroutineContext.ensureActive
309349
*/
310350
public fun CoroutineScope.ensureActive(): Unit = coroutineContext.ensureActive()
311351

312-
313352
/**
314353
* Returns the current [CoroutineContext] retrieved by using [kotlin.coroutines.coroutineContext].
315354
* This function is an alias to avoid name clash with [CoroutineScope.coroutineContext]:

0 commit comments

Comments
 (0)