I'm a bit confused by the new scoping mechanism. I...
# coroutines
u
I'm a bit confused by the new scoping mechanism. I'm trying to migrate some coroutine-based code and stumbled upon this:
Copy code
@Deprecated("No replacement. Group child in a coroutineScope { } block to wait for them")
public suspend fun Job.joinChildren()
However, I don't see how to "group child in a coroutineScope". For example:
Copy code
val networkContext = <http://Dispatchers.IO|Dispatchers.IO>
val networkJob = Job()

private fun onNetworkContext(block: suspend CoroutineScope.() -> Unit) =
    GlobalScope.launch(networkContext + networkJob, block = block)

// invoked from another coroutine:
suspend fun abortAndRetry() {
    networkJob.cancelChildren()
    // how do I replace this properly?
    networkJob.joinChildren()
   // retry ...
 }
j
Depends a but on what you're doing, but the concept is roughly:
Copy code
var networkScope = CoroutineScope(Job() + <http://Dispatchers.IO|Dispatchers.IO>)

private fun onNetworkContext(block: suspend CoroutineScope.() -> Unit) =
    networkScope.launch(block = block)

// invoked from another coroutine:
suspend fun abortAndRetry() {
  networkScope.coroutineContext[Job]?.cancelAndJoin()
  
  // retry ...
  networkScope = CoroutineScope(Job() + <http://Dispatchers.IO|Dispatchers.IO>)
}
The key point is to not use
GlobalScope
if you want to manage the life cycle of child jobs.
e
An interesting use-case. Can you give more details on why exactly you need to separate
onNetworkContext
and
abortAndRetry
? I would be grateful if you create an issue in
<http://github.com/kotlin/kotlinx.coroutines/issues>
so that we can have a discussion here.
Maybe we were too fast to deprecate
joinChildren
, but let’s see if the use-case is strong enough.
Anyway, it is extremely easy to write:
Copy code
networkJob.children().forEach { it.join() }
But beware, the reason that it is deprecated is because you have a race in your code. Nothing prevents a new child to be added between
cancelChildren
and
joinChildren
. So, I strongly suggest to rewrite this code via
networkJob.cancelAndJoin
and then create a new (non-cancelled) parent job for all further children
u
I guess my scenario is a bit weird
e
The code that uses
joinChildren
in inherently racy
u
I'm basically bridging events to coroutines, e.g. I receive events, handle them on a singlethreaded event coroutine context and launch other network-related coroutines from within the event context
I'll think about this some more and maybe create an issue like you suggested tomorrow