A coroutine hierarchy organizes coroutines as parents and children, connecting their execution lifetimes, cancellation, and failures. Structured concurrency manages this hierarchy automatically, preventing forgotten or unnecessarily long-running coroutines. section 15.0
A failed child cancels its sibling
runBlocking { launch { try { while (true) { println("Heartbeat!") delay(500.milliseconds) } } catch (e: Exception) { println("Heartbeat terminated: $e") throw e } } launch { delay(1.seconds) throw UnsupportedOperationException("Ow!") } } The second child throws after one second. Its parent enters cancellation, cancels the heartbeat sibling, and propagates the exception upward. The heartbeat reports a JobCancellationException before the original exception terminates the program. section 18.2.1
The hierarchy provides predictable relationships between concurrent operations:
- Builds parent-child relationships through Job objects associated with coroutine contexts. section 15.3
- Propagates an uncaught child exception to its parent, which cancels the other children and propagates the failure further. section 18.2.1
- Avoids unnecessary work and releases resources when sibling computations can no longer produce a useful common result. section 18.2.1
- Inherits coroutine context along the hierarchy and supports cancellation through suspension points and cancellation functions. section 15.3
Figure 18.1 When child coroutines fail with an uncaught exception, they notify their parent. The parent, in turn, cancels all the sibling coroutines, and propagates the exception further up the coroutine hierarchy.
Trace the failure path from a child coroutine to its parent, across sibling cancellation, and onward through the coroutine hierarchy. section 18.2.1
Use coroutineScope for concurrent decomposition that waits for child results, and use CoroutineScope to associate coroutines with a class lifecycle, typically with SupervisorJob. Avoid GlobalScope in application code because it breaks structured concurrency. section 15.3
