The other day I came across `suspend fun main()` f...
# coroutines
e
The other day I came across
suspend fun main()
for the first time. Where is it documented? How does it work?
w
It’s been added some time ago already https://youtrack.jetbrains.com/issue/KT-17679. There aren’t many details in the issue but it seems like a shortcut for
fun main(args: Array<String>) = runBlocking { ... }
🚫 1
z
I think the only difference is that
suspend fun main
uses the Default dispatcher
e
I think it's not obvious that it uses
runBlocking
under the hood. As this is a
suspend fun
I'm blind to the coroutine scope and context, right? So it's not within my power to know and control whether or not my coroutines run blocking or are backed by many threads?
z
It’s definitely not obvious. You can always use
withContext
to be explicit about that anyway though.
e
So I can escape the synchrony of
runBlocking
that way? 😎 I'll have to try that some time soon
Btw, if I'd had to guess, I would have thought that it was a shorthand for
GlobalSope.launch
z
So I can escape the synchrony of runBlocking that way?
Not really. Regardless of which dispatchers your coroutines are running on,
main
has to block at some point or your program will just exit immediately without running any coroutines.
☝️ 1
w
Yep, I kind of read the issue which said it should be equivalent, but clearly the implementation is different. The bytecode for such suspend main is:
Copy code
// signature ([Ljava/lang/String;Lkotlin/coroutines/Continuation<-Lkotlin/Unit;>;)Ljava/lang/Object;
// declaration:  main(java.lang.String[], kotlin.coroutines.Continuation<? super kotlin.Unit>)
public final static main([Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
Then there’s synthetic method:
Copy code
// $FF: synthetic method
public static void main(String[] var0) {
  RunSuspendKt.runSuspend(new AppKt$$$main(var0));
}
And the
RunSuspend
class uses empty coroutine context:
Copy code
private class RunSuspend : Continuation<Unit> {
    override val context: CoroutineContext
        get() = EmptyCoroutineContext
g
Suspend main doesn't use runBlocking under the hood and not shortcut for GlobalScope.launch, runBlocking is not a part of stdlib, this is a library function The main difference it doesn't provide coroutine scope, but in terms of threading it should be the same as runBlocking on the main thread, it uses main thread