Sobes.tech
Middle

How does scope track coroutine cancellation?

sobes.tech AI

Answer from AI

Scope tracks coroutine cancellation using a Job object. Each CoroutineScope has an associated Job.

When a new coroutine is created within a CoroutineScope, it inherits the Job from that scope as its parent Job.

The cancellation tracking mechanism works as follows:

  1. Scope Cancellation: When cancel() is called on a Job scope, it recursively cancels all its child Jobs.
  2. Child Coroutine Cancellation: When a child coroutine is canceled (for example, via withContext(NonCancellable)) or an unhandled exception occurs, it reports this to its parent Job. The parent Job (of the scope) can then cancel other child coroutines.
  3. Cooperative Cancellation: Coroutines should be cooperative regarding cancellation. This means that within a coroutine, the code should periodically check whether it has been canceled to terminate its work properly. Standard suspend functions (like delay, I/O operations) automatically check the Job's state.

Code can explicitly check for cancellation using isActive or ensureActive():

// Example of checking coroutine activity
suspend fun fetchData() = coroutineScope {
    launch {
        while (isActive) {
            // Perform some long operation
            delay(100) // suspension point - automatically checks for cancellation

            // Or explicitly check
            if (!isActive) {
                break // Exit loop on cancellation
            }
        }
        println("fetchData coroutine completed")
    }
}

Using ensureActive() throws a CancellationException when canceled:

// Using ensureActive()
suspend fun processData() {
    // ... some work ...
    ensureActive() // Throws CancellationException if coroutine is canceled
    // ... continue work only if coroutine is active ...
}

CancellationException is the standard way to propagate a cancellation signal. It should not be considered an error in the context of coroutine cancellation.

Scope, owning a Job, creates a hierarchy of "parent-child" Jobs, which allows cancellation signals to propagate from parent to children. This is a cornerstone of structured concurrency in coroutines.