Hey guys, I have a question that I just posted on ...
# coroutines
i
Hey guys, I have a question that I just posted on Stackoverflow It’s about the coroutine scopes and structured concurrency Could someone please answer it
p
If your
loadUsers
is suspend, caller expects it to return the result by the time it returns (obviously, as the result is literally returned, right?). If it needs to run stuff in parallel to do it’s work, it’s correct to open a scope inside it
Copy code
suspend fun loadUsers(): List<User> {
    coroutineScope {
        //...
    }
}
This form is not right because the scope you are creating has no relation to the coroutine calling your function, meaning if the calling coroutine is cancelled, the parallel work you are running won’t cancel. You’d probably want withContext here instead.
Copy code
suspend fun loadUsers(): List<User> {
    CoroutineScope(Dispatchers.Default).run  {
        //...
    }
}
There’s very few cases that suspend functions should also receive a scope, either by parameter or by receiver, so the following form is weird. It is implying that the inner coroutines launched in the function are bound to a scope that extrapolates the function, so caller would think the function might return before all children coroutines complete
Copy code
suspend fun CoroutineScope.loadUsers(): List<User> {
    //...
}
Generally, it’s either a non-suspend fun receiving a scope (meaning the function is asynchronous), like coroutine builders, or a suspend fun that creates its own scope.
Exceptions are the lambdas passed to coroutine builders like `launch`: they are suspend (they are coroutines after all) and they receive a CoroutineScope, so you can launch new coroutines inside the block respecting structured concurrency (block will only finish when children finish)
So first form is the correct one. Whenever you want to do parallel decomposition of work inside a suspend function, use
coroutineScope {}
i
Thanks @Patrick Steiger That was clear and helpful