Carrascado
08/17/2020, 5:02 PMfun suspend foobar() { dostuff }
, if I call that function from a coroutine, I understand from the documentation that calling foobar will suspend the coroutine, so does that mean foobar won't be executed? Why would I want to do that? It does not make any sense in my head. I know I must be understanding something really wrongZach Klippenstein (he/him) [MOD]
08/17/2020, 5:12 PMsuspend
, that doesn’t mean it will suspend the coroutine, it just means that it might.Carrascado
08/17/2020, 5:13 PMZach Klippenstein (he/him) [MOD]
08/17/2020, 5:13 PMfun foobar(continue: () -> Unit) {
dostuff
continue()
}
fun foobar(continue: () -> Unit) {
executor.execute {
dostuff
continue()
}
}
Carrascado
08/17/2020, 5:15 PMCasey Brooks
08/17/2020, 5:17 PMsuspend
is chopped up into smaller pieces, and those pieces do not need to be processed immediately one after the other. Instead, each block can be suspended to be resumed as some later point in the future, potentially on a different thread. The compiler does the work of chopping a suspend
function into these chunks, and the runtime library does the work of suspending/resuming these chunks.Zach Klippenstein (he/him) [MOD]
08/17/2020, 5:18 PMCasey Brooks
08/17/2020, 5:20 PMCarrascado
08/17/2020, 5:21 PMCasey Brooks
08/17/2020, 5:24 PMsuspend
function is called, which is called a “suspension point”. This is why suspend
functions can only be called within other suspend
functions/lambdas. By being inside a suspend
function, the compiler knows to start chopping things up when calling other suspend
functionssuspend
functions inside itCarrascado
08/17/2020, 5:26 PMCasey Brooks
08/17/2020, 5:30 PMCarrascado
08/17/2020, 5:39 PMZach Klippenstein (he/him) [MOD]
08/17/2020, 5:39 PMHow does the compiler know where to make the “chunks”?I think it’s probably more accurate to say this happens at the special
suspendCoroutine
function. This is the function that actually gives you a callback that represents the rest of the function.Carrascado
08/17/2020, 5:43 PMCasey Brooks
08/17/2020, 5:51 PMyou will need a policy to decide what coroutine is resumedAgain, yes.
Dispatchers
are that policy. But even Java’s exceptions are a layer of error-handling built above the OS level. Most languages and frameworks need to implement their own form of error-handling specific to that domain, and this, too, is part of coroutines. Under-the-hood, it’s basically just throwing and catching exceptions with a small bit of logic to track which chunks threw the exception and which ones caught it (basically, the Job
interface).
how can this work so efficientlyIf you’re constantly jumping between threads, it’s just as expensive as a normal thread context-switch. But most code don’t jump between threads that often, just a couple of times, and when it’s “jumping” between chunks without that thread switch it’s little more than a regular function call
Carrascado
08/17/2020, 5:59 PMephemient
08/17/2020, 6:04 PMDeepRecursiveFunction
that allows you to write a deeply recursive function as a suspend function. with how the compiler automatically chunks up suspend functions, this converts stack usage into heap usageCasey Brooks
08/17/2020, 6:07 PMThread.sleep()
), then coroutines can’t do too much. Ultimately, it’s just running normal code in smaller chunks interwoven in clever ways, but they can’t really do anything in the middle of a chunk.
CPU-bound tasks are essentially just really large chunks, and as such the framework can’t fix that for you. But they can make it easier to move that giant chunk to the threads best suited for processing it (Dispatchers. Default
), or providing you tools for breaking a large blocking code chunk into smaller chunks (suspendCoroutine
Zach mentioned above)Carrascado
08/17/2020, 6:10 PMColton Idle
08/17/2020, 7:48 PMandylamax
08/17/2020, 11:18 PMsuspending
but also what structured concurrency
fully meant in the context of coroutinesIlmir Usmanov [JB]
08/18/2020, 12:06 AMCarrascado
08/18/2020, 4:18 PMCasey Brooks
08/18/2020, 4:24 PMCarrascado
08/18/2020, 4:39 PM