christophsturm
04/25/2021, 6:32 PMGlobalScope.launch(Dispatchers.Unconfined) {
coroutineScope {
...
}
}
a good way to use structured concurrency in an async handler that does not know about coroutines?Zach Klippenstein (he/him) [MOD]
04/25/2021, 8:32 PMchristophsturm
04/26/2021, 7:01 AM....launch(Dispatchers.Unconfined) {
// ....do stuff
// scope should end here
}
val requestScope = CoroutineScope(Dispatchers.Unconfined)
exchange.addExchangeCompleteListener { requestScope.cancel()
}
requestScope.launch {
....
}
})
}
Zach Klippenstein (he/him) [MOD]
04/26/2021, 2:59 PMIs there no way to have create a block that has a local scope that ends at the end of the block?All the standard coroutine builders (
launch
, async
, runBlocking
, etc) already do that. Remember, CoroutineScope
is just syntactic sugar around a CoroutineContext
, which is just a map, and structured concurrency is implemented via the Job
stored in the context. Whenever you create a new coroutine, it gets its own Job
, and that Job
is stored in the context wrapped by the scope that is the receiver to the block passed to them.christophsturm
04/26/2021, 3:48 PMexchange.addExchangeCompleteListener { requestScope.cancel()
}
launch
, async
, runBlocking
, etc) already do that" <= even when invoked on global scope?Zach Klippenstein (he/him) [MOD]
04/26/2021, 3:55 PMparentScope.launch { childScope = this }
childScope.coroutineContext.job
will always be a child of parentScope.coroutineContext.job
, even if parentScope
happens to be GlobalScope
. This is what makes structured concurrency work. (Technically, GlobalScope
doesn’t actually have a Job I believe, in which case childScope.coroutineContext.job
is actually a root job, but that is effectively the same as if GlobalScope
did have a job that was just never cancelled)christophsturm
04/26/2021, 4:48 PMZach Klippenstein (he/him) [MOD]
04/26/2021, 4:57 PMchristophsturm
04/26/2021, 6:32 PMlouiscad
04/26/2021, 6:32 PMZach Klippenstein (he/him) [MOD]
04/26/2021, 6:37 PMchristophsturm
04/26/2021, 7:46 PM