Skip to content

Improve CoroutineScope extensions documentation #4269

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Nov 7, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 52 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:
* A coroutine cancallation [is cooperative](https://kotlinlang.org/docs/cancellation-and-timeouts.html#cancellation-is-cooperative)
* and normally, the cancellation machinery happens when the coroutine *suspends*, for example,
* when trying to read from a [channel][kotlinx.coroutines.channels.Channel] that is empty.
*
* Sometimes, a coroutine does not need to do any of such operations, but still wants to be a cooperative
* and respect cancellation.
*
* [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,41 @@ 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].
* Ensures that current scope is [active][CoroutineScope.isActive] and throws the [CancellationException] that was the
* scope's cancellation cause otherwise.
*
* 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].
* A coroutine cancallation [is cooperative](https://kotlinlang.org/docs/cancellation-and-timeouts.html#cancellation-is-cooperative)
* and normally, the cancellation machinery happens when the coroutine *suspends*, for example,
* when trying to read from a [channel][kotlinx.coroutines.channels.Channel] that is empty.
*
* Sometimes, a coroutine does not need to do any of such operations, but still wants to be a 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] in a receiver position:
Expand Down