Coroutine scope function instances
See Coroutine scope function and Error Boundary for detailed info on scope functions.
- Inherits a context from its parent, while creating a new Regular Job that inherits from parent Job.
- Uncaught Exception from one child:
- Waits for all its children before it can finish itself (when children do not throw)
- Cancels all its children when the parent is cancelled
// This is pseudo-code for purposes of understanding !!NOT TO BE USED AS IS!!
suspend fun <T> coroutineScope(block: suspend CoroutineScope.() -> T): T {
// Get the current coroutine context
val currentContext = coroutineContext
// Create a new Job that's a child of the current job
val scopeJob = Job(parent = currentContext[Job])
// Create a new scope with the new job
val scope = CoroutineScope(currentContext + scopeJob)
try {
// Execute the block and get result
val result = block(scope)
// This conceptually "waits" for all children to complete
// (In reality this would need to be done differently)
scopeJob.complete() // Signal no more children will be added
scopeJob.join() // Wait for existing children
return result
} catch (e: Exception) {
// Cancel all children on any exception
scopeJob.cancelChildren()
throw e
}
}
Another function that behaves a lot like coroutineScope is withTimeout. It also creates a scope and returns a value. Actually, withTimeout with a very big timeout behaves just like coroutineScope. The difference is that withTimeout additionally sets a time limit for its body execution. If it takes too long, it cancels this body and throws TimeoutCancellationException (a subtype of CancellationException).
Beware that withTimeout throws TimeoutCancellationException, which is a subtype of CancellationException (the same exception that is thrown when a coroutine is cancelled). So, when this exception is thrown in a coroutine builder, it only cancels it and does not affect its parent (as explained in the previous chapter). - Kotlin Coroutines Deep Dive
Relationships
Gotchas
The withContext function is similar to coroutineScope, but it additionally allows some changes to be made to the scope. The CoroutineContext provided as an argument to this function overrides the context from the parent scope (the same way as in coroutine builders). This means that withContext(EmptyCoroutineContext) and coroutineScope() behave in exactly the same way.
The function withContext is often used to set a different coroutine scope for part of our code. Usually, you should use it together with Dispatcher. - Kotlin Coroutines Deep Dive
Relationships
Gotchas
The supervisorScope function also behaves a lot like coroutineScope: it creates a CoroutineScope that inherits from the outer scope and calls the specified suspend block in it. The difference is that it overrides the context’s Job with Supervisor-Job, so it is not cancelled when a child raises an exception.
supervisorScope is mainly used in functions that start multiple independent tasks. - Kotlin Coroutines Deep Dive
Highlight
- Does NOT cancel when child raises an exception.
- Does NOT cancel children when child raises an exception.
- Waits for ALL children, even failing ones, even after some have failed and threw.
- Collects ALL exceptions from co-routines.
Notes
Children
Backlinks