I am reading Kotlin Coroutines Deep Dive by Marcin Moskala, and I have a problem understanding suspendCoroutine function.
AFAIK, suspendCoroutine is a low-level API that helps you possess the continuation object before the coroutine suspends and do some action with it.
As Marcin Moskala states,
it ends with a lambda expression ({ }). The function passed as an argument will be invoked before the suspension. This function gets a continuation as an argument. The suspendCoroutine function makes it possible to use the continuation just before the suspension. After the suspendCoroutine call, it would be too late.
So, what's really happening here? I have the following questions:
I am aware of this answer, but still no understanding
I also know that technically this continuation object can be saved, coroutine indeed suspends, and later we can call .resume on saved object on some other control flow, but this scenario seems to be misuse of coroutines API due to memory leaks.
Is it just a wrapper on callbacks so as to avoid callback hell?
Please, clarify the idea of using suspendCoroutine.
suspendCoroutine
is used to bridge other asynchronous models like callbacks, futures, etc. with coroutines. It "converts" existing asynchronous code to suspending.
Generally speaking, the usage pattern is like this:
resume
to resume the coroutine. How/where/when we call resume
depends highly on the type of the asynchronous operation and its API.Answering your questions directly:
Ad.1. If we put resume
directly in the lambda (which could make sense in some cases), I suspect it won't even suspend. But it can also suspend and resume immediately. I think the function doesn't guarantee any of these behaviors.
Ad.2. If we put synchronous, blocking code directly in the lambda, that means we blocked the coroutine, in a similar way as if we don't at all use suspendCoroutine
. This is incorrect way of using suspendCoroutine
. It is generally expected that the lambda passed to suspendCoroutine
only schedules the asynchronous operation and finishes almost immediately.
I also know that technically this continuation object can be saved, coroutine indeed suspends, and later we can call .resume on saved object on some other control flow, but this scenario seems to be misuse of coroutines API due to memory leaks.
Is it just a wrapper on callbacks so as to avoid callback hell?
This is not a misuse of coroutines API, this is exactly how we are supposed to use suspendCoroutine
. It doesn't cause any memory leaks, assuming the original code based on callbacks didn't cause them.