how mechanism of suspend functions are been paused...
# coroutines
a
how mechanism of suspend functions are been paused and resumed in thread and also how coroutines are unblocking the main thread, anyone know please reply.
h
Try watching this and see if that helps:

https://www.youtube.com/watch?v=_hfBv0a09Jcâ–¾

t
it's a compiler trick. The compiler breaks up your code into separate methods every time it sees you call a
suspend
function. It figures out what state you need (local vars, etc) and makes sure they are available to all the methods.
if you look at the java code for a simple function that calls several
suspend
-ing functions, it actually uses a big java switch statment w/ each case: being another section of your function.
so basically : It's all callbacks under the hood.
a
thanks @TwoClocks, I'm also looking for answer how when we use suspend function it unblocks the main thread, i tried wwatching the videos but I could find a answer for this part alone. Considering th fact that coroutines are light-weight threads and we can run as many of them in a single thread, how are unblocking is part which i don't get it.
t
the code that suspends them (via a continuation) just starts them again.
you can see a minimal example of a suspending coroutine w/ no usage of the coroutines library here : https://stackoverflow.com/a/64421487
coroutines are not threads. You do yourself a disservice by thinking of them as such. They are "continuations". Or a compiler trick to hide context and issue calls backs. Sorta like interrupts from back in the day. You can layer threading on top of coroutines so that suspending functions can be resumed on different threads, but that's just the same as saying "I can call this function from a different thread". It doesn't really have anything to do with threading at all.
a
thanks @TwoClocks đŸ™‚
u
@Ajaydeepak07 what is your background? Android, iOS, JavaFX? The whole story need the concept of run loop. So I can try to translate the explanation to your platform
a
Android.
sure looking forward to...
u
first of: the unblokcing happens by just returning.
let’s say you have:
Copy code
println("Start")
delay(1000)
// do the rest
println("Done")
return
then as a mental model you can imagine this to be translated to:
Copy code
Handler mainHandler = new Handler(Looper.getMainLooper());
println("Start")
mainHandler.postDelayed { 
  // do the rest
  println("Done")
}
return
I asked for the platform because the details are in the dispatcher. On android it will use post (and postDelayed for
delay()
)
This is only a mental model though. because the real implementation will actually post the whole function for execution to the main thread again and synthesise some code in your function to jump forward to where you left of.
That’s also the reason, why suspend methods can only be called from other suspend methods. because when a suspend method first returns, it does not have a result to return. It needs the caller to get the result later, asynchronoiusly
Here comes a documented , cleaned up decompile of the above mentioned test code:
Copy code
public final Object test(@NotNull Continuation<? super Unit> $completion) {
         // Note: $continuation.label tells us where to continue. Initially it will be 0
        switch ($continuation.label) {
            case 0: {
                System.out.println("Start");

                // Prepare for suspending
                
                // Save state
                $continuation.L$0 = this;
                // Remember wheree to continue
                $continuation.label = 1;
                // Call delay. Just like our own test function this will return before being done
                // When delay is really done, we will be called again with L$0 and label as we
                // Set it aboove
                v0 = DelayKt.delay((long)1000L, (Continuation)$continuation);
                // v0 can contain a marker that it is not done yet (COROUTINE_SUSPENDED) or a real
                // return value
                var6_4 = IntrinsicsKt.getCOROUTINE_SUSPENDED();
                if (v0 == var6_4) {
                    // If delay suspended, we suspend as well, waiting for it's answer
                    return var6_4;
                }
                // Otherwise continue imediately with the result of delay
                ** GOTO lbl25
            }
            case 1: {
                // restore state
                this = (ScopedViewModel)$continuation.L$0;
                // Get result of delay call
                v0 = $continuation.result;
lbl25:
                // Do the rest
                System.out.println("Done");
                // Return real result, not COROUTINE_SUSPENDED, indicating that we completed our jobdo not want to
                // and need not be called again
                return Unit.INSTANCE;
            }
        }
    }
and the dispatcher will basically call:
Copy code
postDelayed {
  test($continuation)
}
to let us continue at label
1