azabost
07/28/2021, 6:38 PMsuspendCancellableCoroutine
to bridge some 3rd party API in my app. It's working OK-ish but I'm wondering how reliable it is considering the callback I need to implement requires returning some values, e.g.
suspend fun displayFoo() {
val foo = getFoo()
delay(10_000)
println(foo)
}
suspend fun getFoo(): Foo = suspendCancellableCoroutine { continuation ->
val callback = FooLoader
.addListener(object : RequestListener<Foo> {
override fun onLoadFailed(e: FooException): Boolean {
continuation.resumeWithException(e)
return false
}
override fun onLoadSuccessful(foo: Foo): Boolean {
continuation.resume(foo)
return false
}
})
.load()
continuation.invokeOnCancellation {
callback.cancel()
}
}
How is this actually working?
Does the thread calling onLoadSuccessful
execute the full delay(10_000)
before returning return false
or is it executed as soon as the calling thread is "free" (because delay
is suspending, not blocking)?
I'm also wondering what would happen if the continuation failed e.g.
suspend fun displayFoo() {
val foo = getFoo()
delay(10_000)
throw NPE
}
Nick Allen
07/28/2021, 7:08 PMcontinuation.resume(foo)
will not block when the resumed coroutine later suspends.
Usually, it's just adding to a CoroutineDispatcher's event queue so it's not waiting at all. In some cases like with Dispatchers.Unconfined or Dispatchers.Main.immediate it will actually start running the resumed code directly but it will return as soon as the calling thread is free.Nick Allen
07/28/2021, 7:22 PMsuspendCancellableCoroutine
kinda just exposes how suspend methods actually work when they suspend. When they suspend, they actually just setup code to invoke the continuation (hidden parameter added by suspend keyword ) later and then they return right away. This returning right away is how it frees up the thread.
So in the compiled code, delay(10_000)
actually just sets up a timer callback, and then returns immediately and displayFoo returns immediately and all the way up until it get's to the CoroutineDispatcher. println(foo)
and any other code waiting to run is wrapped up in the time callback.Nick Allen
07/28/2021, 7:31 PM