I'm trying to understand the difference between
suspendCoroutine
and
suspendCancellableCoroutine
when writing a wrapper around an external callback-based API.
My original understanding was that the difference between the two is just whether or not the continuation you get access to in the block has methods that lets the block you write right there cancel it. So you should use the latter if the API you're wrapping has some way of indicating that it cancelled so that you would want to cancel the suspended coroutine, but otherwise there's no need to use the longer-named function.
But when I test these out,
fun main() = runBlocking {
withTimeout(10) {
suspendCancellableCoroutine { continuation: CancellableContinuation<Unit> -> }
}
}
throws a TimeoutCancellationException (as I expected), but
fun main() = runBlocking {
withTimeout(10) {
suspendCoroutine { continuation: Continuation<Unit> -> }
}
}
appears to hang, which surprises me.
Does that imply that when you run suspendCoroutine then your current coroutine can't be cancelled "from above"? In that case, why would you ever use suspendCoroutine instead of suspendCancellableCoroutine?