Skip to content

Commit

Permalink
Improve CoroutineScope extensions documentation (#4269)
Browse files Browse the repository at this point in the history
Co-authored-by: Dmitry Khalanskiy <[email protected]>
  • Loading branch information
qwwdfsad and dkhalanskyjb authored Nov 7, 2024
1 parent 96cad1f commit 75e72cd
Showing 1 changed file with 51 additions and 12 deletions.
63 changes: 51 additions & 12 deletions kotlinx-coroutines-core/common/src/CoroutineScope.kt
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,13 @@ public interface CoroutineScope {
* Adds the specified coroutine context to this scope, overriding existing elements in the current
* scope's context with the corresponding keys.
*
* This is a shorthand for `CoroutineScope(thisScope.coroutineContext + context)`.
* This is a shorthand for `CoroutineScope(thisScope.coroutineContext + context)` and can be used as
* a combinator with existing constructors:
* ```
* class MyActivity {
* val uiScope = MainScope() + CoroutineName("MyActivity")
* }
* ```
*/
public operator fun CoroutineScope.plus(context: CoroutineContext): CoroutineScope =
ContextScope(coroutineContext + context)
Expand Down Expand Up @@ -117,13 +123,30 @@ public fun MainScope(): CoroutineScope = ContextScope(SupervisorJob() + Dispatch
/**
* Returns `true` when the current [Job] is still active (has not completed and was not cancelled yet).
*
* Check this property in long-running computation loops to support cancellation:
* Coroutine cancallation [is cooperative](https://kotlinlang.org/docs/cancellation-and-timeouts.html#cancellation-is-cooperative)
* and normally, it's checked if a coroutine is cancelled when it *suspends*, for example,
* when trying to read from a [channel][kotlinx.coroutines.channels.Channel] that is empty.
*
* Sometimes, a coroutine does not need to perform suspending operations, but still wants to be cooperative
* and respect cancellation.
*
* The [isActive] property is inteded to be used for scenarios like this:
* ```
* while (isActive) {
* // do some computation
* val watchdogDispatcher = Dispatchers.IO.limitParallelism(1)
* fun backgroundWork() {
* println("Doing bookkeeping in the background in a non-suspending manner")
* Thread.sleep(100L) // Sleep 100ms
* }
* // Part of some non-trivial CoroutineScope-confined lifecycle
* launch(watchdogDispatcher) {
* while (isActive) {
* // Repetitively do some background work that is non-suspending
* backgroundWork()
* }
* }
* ```
*
* This function returns `true` if there is no [job][Job] in the scope's [coroutineContext][CoroutineScope.coroutineContext].
* This property is a shortcut for `coroutineContext.isActive` in the scope when
* [CoroutineScope] is available.
* See [coroutineContext][kotlin.coroutines.coroutineContext],
Expand Down Expand Up @@ -292,24 +315,40 @@ public fun CoroutineScope.cancel(cause: CancellationException? = null) {
public fun CoroutineScope.cancel(message: String, cause: Throwable? = null): Unit = cancel(CancellationException(message, cause))

/**
* Ensures that current scope is [active][CoroutineScope.isActive].
* Throws the [CancellationException] that was the scope's cancellation cause if the scope is no longer [active][CoroutineScope.isActive].
*
* If the job is no longer active, throws [CancellationException].
* If the job was cancelled, thrown exception contains the original cancellation cause.
* This function does not do anything if there is no [Job] in the scope's [coroutineContext][CoroutineScope.coroutineContext].
* Coroutine cancallation [is cooperative](https://kotlinlang.org/docs/cancellation-and-timeouts.html#cancellation-is-cooperative)
* and normally, it's checked if a coroutine is cancelled when it *suspends*, for example,
* when trying to read from a [channel][kotlinx.coroutines.channels.Channel] that is empty.
*
* Sometimes, a coroutine does not need to perform suspending operations, but still wants to be cooperative
* and respect cancellation.
*
* This method is a drop-in replacement for the following code, but with more precise exception:
* [ensureActive] function is inteded to be used for these scenarios and immediately bubble up the cancellation exception:
* ```
* if (!isActive) {
* throw CancellationException()
* val watchdogDispatcher = Dispatchers.IO.limitParallelism(1)
* fun backgroundWork() {
* println("Doing bookkeeping in the background in a non-suspending manner")
* Thread.sleep(100L) // Sleep 100ms
* }
* fun postBackgroundCleanup() = println("Doing something else")
* // Part of some non-trivial CoroutineScope-confined lifecycle
* launch(watchdogDispatcher) {
* while (true) {
* // Repeatatively do some background work that is non-suspending
* backgroundWork()
* ensureActive() // Bail out if the scope was cancelled
* postBackgroundCleanup() // Won't be invoked if the scope was cancelled
* }
* }
* ```
* This function does not do anything if there is no [Job] in the scope's [coroutineContext][CoroutineScope.coroutineContext].
*
* @see CoroutineScope.isActive
* @see CoroutineContext.ensureActive
*/
public fun CoroutineScope.ensureActive(): Unit = coroutineContext.ensureActive()


/**
* Returns the current [CoroutineContext] retrieved by using [kotlin.coroutines.coroutineContext].
* This function is an alias to avoid name clash with [CoroutineScope.coroutineContext]:
Expand Down

0 comments on commit 75e72cd

Please sign in to comment.