Exerosis
06/11/2023, 5:38 AMoverride fun dispatch(context: CoroutineContext, block: Runnable) {
How can I best support cancellation in my dispatcher here? Right now if you cancel and join from the main thread loop, the dispatched task will never get run. So it just deadlocks 😐Rohan Maity
06/14/2023, 12:54 PMgildor
06/14/2023, 3:49 PMExerosis
06/15/2023, 6:32 AMfun somethingCalledFromJava() {
blocking {
withContext(<http://Dispatchers.IO|Dispatchers.IO>) {
//do something
withContext(Dispatchers.Application) {
delay(30.seconds)
callSomeListenersThatAreSuspend()
}
}
}
}
If we simply did runBlocking(Dispatchers.Application) the application dispatcher wouldn't be able to do anything since you would never move to the next cycle. But using this system we can block the current cycle and intercept calls that would dispatch to the next cycle and patch them into the event loop. This works flawlessly, the marker even allows you to switch contexts backk and forth without losing track of what calls to Dispatchers.Application are async vs required to unblock the main thread.
The issue is that you might make a call like:
val task = scope.launch(Dispatchers.Application) {
//some long running cancellable task
}
//somewhere else from the Application thread:
blocking { task.cancelAndJoin() }
The concern is if dispatch is called as part of that launch at the same time as you call cancel and join. It can deadlock since the dispatched block will never be run as soon as you join. (and this appears to be happening in practice) It's possible I'm seeing another problem and totally missunderstood the issue. But otherwise I need to find a way to detect cancel and join basically.