So, this might be a dumb question, but why is it p...
# coroutines
d
So, this might be a dumb question, but why is it preferred to use
continuation.resumeWithException
instead of simply throwing the exception here?
Copy code
fun main() {
    runBlocking {
        try {
            suspendCoroutine<Unit> { continuation ->
                val e = IllegalArgumentException("foo")
                continuation.resumeWithException(e)
                //throw e
            }
        }
        catch (_: IllegalArgumentException) {
            println("handled")
        }
    }
}
IOW, how is an exception that is thrown from the
block
of
suspendCoroutine
handled? The implementation is intrinsic and not visible...
y
Both should be equivalent here I believe.
r
On JVM at least, throwing Exceptions is generally considered to be quite expensive so the idea of throwing an Exception that will be immediately caught and rethrown in a different context may be bad for performance (probably it won’t be a problem unless you do it a lot)
But I’d also slightly favour it because it’s consistent with the regular
continuation.resume
API and helps to ensure no path leads to coroutine unresumed
d
Ok, what if I expand the scenario to this:
Copy code
fun main() {
    runBlocking {
        try {
            suspendCoroutine { continuation ->
                object: Thread() {
                    override fun run() {
                        try {
                            throw IllegalArgumentException()
                        } catch (throwable: Throwable) {
                            continuation.resumeWithException(throwable)
                        }
                    }
                }.start()
            }
        }
        catch (_: IllegalArgumentException) {
            println("handled")
        }
    }
}
My colleague tells me that
resumeWithException
is needed here, otherwise the outer coroutine is leaking and I get a potential deadlock. My main issue here is not the
resumeWithException
, I understand that I want to redirect some exceptions onto the calling stack, but that all `Throwable`s are redirected, including everything that inherits from
Error
(e.g.
OutOfMemoryError
). I have a hard time believing this is a good pattern to forward these to the calling stack as well. Opinions?