# Structured Concurrency and Cancellation — Kotlin

Source: https://www.skillbyai.com/en/kotlin/co-structured

> Scopes, Jobs, cancellation and failure propagation.

## Every coroutine has a parent

With **structured concurrency**, coroutines are launched in a `CoroutineScope`, and a parent does not complete until all its children complete. If a child fails, the failure cancels the parent and its other children by default; `supervisorScope` or a `SupervisorJob` lets siblings fail independently. Cancelling a scope cancels all its children, which prevents leaked work, for example `viewModelScope` on Android is cancelled when the ViewModel is cleared. Cancellation is **cooperative**: suspending functions from kotlinx.coroutines check for it and throw `CancellationException`; CPU-heavy loops should call `ensureActive()` or `yield()`. Do not swallow `CancellationException` in catch blocks, and use `withTimeout` for deadlines. Avoid `GlobalScope`, which escapes structure.

## Cancellation and timeouts

Cooperative cancellation in practice.

```kotlin
import kotlinx.coroutines.*

suspend fun crunch(items: List<Int>): Long = withContext(Dispatchers.Default) {
    var sum = 0L
    for (item in items) {
        ensureActive()                 // honour cancellation in a CPU loop
        sum += item.toLong() * item
    }
    sum
}

suspend fun loadWithDeadline(): String? =
    withTimeoutOrNull(2_000) {         // null if it takes longer than 2 seconds
        delay(500)
        "loaded"
    }

class Worker(private val scope: CoroutineScope) {
    private var job: Job? = null
    fun start() { job = scope.launch { while (isActive) { delay(1_000) /* poll */ } } }
    fun stop() { job?.cancel() }
}
```

## Rethrow CancellationException

A blanket `catch (e: Exception)` inside a coroutine also catches `CancellationException`. Rethrow it (or catch narrower exception types) so cancellation still propagates.

**Quiz:** What happens to child coroutines when their scope is cancelled?

- [ ] They are restarted
- [ ] They keep running in GlobalScope
- [x] They are cancelled too
- [ ] Nothing; children are independent of scopes

*Answer:* They are cancelled too. Structured concurrency ties child lifetimes to the parent.
