https://kotlinlang.org logo
#coroutines
Title
# coroutines
d

dave08

11/22/2018, 8:32 PM
Is it better to be using a coroutineScope when all there is is one operation there? To be truthful, I made my own
launchInScope
function to do the same thing... just wondering if that's really the intention. If so, why not just abstract away the whole Job concept and let the end user deal only with scopes?
l

louiscad

11/23/2018, 8:57 AM
@dave08 In case of
launch
, you already can have a `try`/`catch` block, and the scope in which
launch
is called can be a supervisor or have a
SupervisorJob()
, so you should never need something like
launchInScope
.
d

dave08

11/23/2018, 10:26 AM
So why is async so different? I thought superviserscope works on them too? @louiscad
l

louiscad

11/23/2018, 10:37 AM
@dave08
async
is designed to cancel its scope so other work is cancelled. It is basically a fail fast technique. If you don't put it in a local
coroutineScope { … }
, it will cancel the upper scope, possibly without a way to recover. supervisor is to stop cancellation propagation, which is suitable for base scopes like the ones you would have in a UI component, at the root server code, etc…
d

dave08

11/23/2018, 10:40 AM
So it cancels even a supervisor scope, if not in its own scope? Even with a try catch around it @louiscad?
l

louiscad

11/23/2018, 10:44 AM
@dave08 Try to understand this by running it and looking into it on
<http://play.kotl.in|play.kotl.in>
,
<http://try.kotl.in|try.kotl.in>
or locally on your machine:
Copy code
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*

suspend fun main() {
    coroutineScope {
        println(1)
        val channel = actor<Int> {
            consumeEach {
                try {
                    println("Attempting to do work for $it")
                    coroutineScope {
                        val stuff1 = async {
                            check(it != 2)
                            it
                        }
                        delay(100)
                        stuff1.await()
                    }
                    println("Work done for $it")
                } catch (e: IllegalStateException) {
                    println("Caught it!")
                }
            }
        }
        repeat(5) {
            channel.send(it)
        }
        launch {
            delay(1000)
            println(2)
        }
        println(3)
        println(4)
        delay(2000)
        channel.close()
    }
    println(5)
}
Run it and see the
IllegalStateException
being caught successfully. Then, remove the inner
coroutineScope { … }
and run again -> see it fail. Then, replace the outer
coroutineScope { … }
with
supervisorScope { … }
and run again -> see it fail, with limited propagation.
d

dave08

11/23/2018, 10:48 AM
Thanks for the example! Will do, when I'll be by a computer 🙂. I think there was talk about simplifying the mental model of coroutines... this is a nice example of where a beginner (even intermediate...) wouldn't have a clue of what to expect...
@louiscad I tried the example, but I still don't understand. The try without the scope and the one with supervisorScope both crash at 2 and give the same results, why is that? And what do you mean by limited propagation?
l

louiscad

11/25/2018, 11:27 AM
@dave08 Doesn't the supervisorScope one let the other coroutines out of it run?
d

dave08

11/25/2018, 11:27 AM
https://play.kotlinlang.org/#eyJ2ZXJzaW9uIjoiMS4zLjAiLCJwbGF0Zm9ybSI6ImphdmEiLCJhcmdzIjoiIiwibm9uZU1hcmtlcnMiOnRydWUsInRoZW1lIjoiaWRlYSIsImZvbGRlZEJ1dHRvbiI6dHJ1ZSwicmVhZE9ubHkiOmZhbHNlLCJjb2RlIjoiaW1wb3J0IGtvdGxpbnguY29yb3V0aW5lcy4qXG5pbXBvcnQga290bGlueC5jb3JvdXRpbmVzLmNoYW5uZWxzLipcblxuc3VzcGVuZCBmdW4gbWFpbigpIHtcbiAgICBjb3JvdXRpbmVTY29wZSB7XG4gICAgICAgIHByaW50bG4oMSlcbiAgICAgICAgdmFsIGNoYW5uZWwgPSBhY3RvcjxJbnQ+IHtcbiAgICAgICAgICAgIGNvbnN1bWVFYWNoIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICBwcmludGxuKFwiQXR0ZW1wdGluZyB0byBkbyB3b3JrIGZvciAkaXRcIilcbi8vICAgICAgICAgICAgICAgICAgICAgc3VwZXJ2aXNvclNjb3BlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbCBzdHVmZjEgPSBhc3luYyB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlY2soaXQgIT0gMilcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZGVsYXkoMTAwKVxuICAgICAgICAgICAgICAgICAgICAgICAgc3R1ZmYxLmF3YWl0KClcbi8vICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBwcmludGxuKFwiV29yayBkb25lIGZvciAkaXRcIilcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlOiBJbGxlZ2FsU3RhdGVFeGNlcHRpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgcHJpbnRsbihcIkNhdWdodCBpdCFcIilcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmVwZWF0KDUpIHtcbiAgICAgICAgICAgIGNoYW5uZWwuc2VuZChpdClcbiAgICAgICAgfVxuICAgICAgICBsYXVuY2gge1xuICAgICAgICAgICAgZGVsYXkoMTAwMClcbiAgICAgICAgICAgIHByaW50bG4oMilcbiAgICAgICAgfVxuICAgICAgICBwcmludGxuKDMpXG4gICAgICAgIHByaW50bG4oNClcbiAgICAgICAgZGVsYXkoMjAwMClcbiAgICAgICAgY2hhbm5lbC5jbG9zZSgpXG4gICAgfVxuICAgIHByaW50bG4oNSlcbn0ifQ==
l

louiscad

11/25/2018, 11:28 AM
What a link!
🤓 1
d

dave08

11/25/2018, 11:28 AM
https://play.kotlinlang.org/#eyJ2ZXJzaW9uIjoiMS4zLjAiLCJwbGF0Zm9ybSI6ImphdmEiLCJhcmdzIjoiIiwibm9uZU1hcmtlcnMiOnRydWUsInRoZW1lIjoiaWRlYSIsImZvbGRlZEJ1dHRvbiI6dHJ1ZSwicmVhZE9ubHkiOmZhbHNlLCJjb2RlIjoiaW1wb3J0IGtvdGxpbnguY29yb3V0aW5lcy4qXG5pbXBvcnQga290bGlueC5jb3JvdXRpbmVzLmNoYW5uZWxzLipcblxuc3VzcGVuZCBmdW4gbWFpbigpIHtcbiAgICBjb3JvdXRpbmVTY29wZSB7XG4gICAgICAgIHByaW50bG4oMSlcbiAgICAgICAgdmFsIGNoYW5uZWwgPSBhY3RvcjxJbnQ+IHtcbiAgICAgICAgICAgIGNvbnN1bWVFYWNoIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICBwcmludGxuKFwiQXR0ZW1wdGluZyB0byBkbyB3b3JrIGZvciAkaXRcIilcbiAgICAgICAgICAgICAgICAgICAgc3VwZXJ2aXNvclNjb3BlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbCBzdHVmZjEgPSBhc3luYyB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlY2soaXQgIT0gMilcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgZGVsYXkoMTAwKVxuICAgICAgICAgICAgICAgICAgICAgICAgc3R1ZmYxLmF3YWl0KClcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBwcmludGxuKFwiV29yayBkb25lIGZvciAkaXRcIilcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlOiBJbGxlZ2FsU3RhdGVFeGNlcHRpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgcHJpbnRsbihcIkNhdWdodCBpdCFcIilcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmVwZWF0KDUpIHtcbiAgICAgICAgICAgIGNoYW5uZWwuc2VuZChpdClcbiAgICAgICAgfVxuICAgICAgICBsYXVuY2gge1xuICAgICAgICAgICAgZGVsYXkoMTAwMClcbiAgICAgICAgICAgIHByaW50bG4oMilcbiAgICAgICAgfVxuICAgICAgICBwcmludGxuKDMpXG4gICAgICAgIHByaW50bG4oNClcbiAgICAgICAgZGVsYXkoMjAwMClcbiAgICAgICAgY2hhbm5lbC5jbG9zZSgpXG4gICAgfVxuICAgIHByaW50bG4oNSlcbn0ifQ==
The one without supervisor and the one with...
I guess they're encoding the code in the editor into the url?
l

louiscad

11/25/2018, 11:29 AM
@dave08 You misread what I told you initially
d

dave08

11/25/2018, 11:30 AM
Oh, I see, the OUTER scope!
l

louiscad

11/25/2018, 11:30 AM
I said to use
supervisorScope
in place of the OUTER
coroutineScope
d

dave08

11/25/2018, 11:30 AM
But why should it fail when the inner scope is replaced?
l

louiscad

11/25/2018, 11:31 AM
It doesn't fail when there's an inner scope
The inner scope makes cancellation caused by failure recoverable
d

dave08

11/25/2018, 11:32 AM
I mean when the inner scope is a supervisorScope... I thought the only difference was in the automatic cancellation of the children...
l

louiscad

11/25/2018, 11:32 AM
The inner scope should not be a supervisor in this case
d

dave08

11/25/2018, 11:33 AM
What is the difference? 🤔
In this case, I mean
Also, replacing the OUTER one, seems to give the same result...
l

louiscad

11/25/2018, 11:35 AM
The supervisor needs to ignore failure/cancellation of children, so it doesn't cancel other coroutines launched from it, unless it gets cancelled itself explicitly, and doesn't propagate cancellation or failure to its parent unless again, it is cancelled explicitly
Yes, it fails too with outer supervisor because the exception is uncaught, which causes the program to be stopped.
d

dave08

11/25/2018, 11:38 AM
So, to see the difference, I would need to add a try/catch around the OUTER supervisorScope?
Because it seems like the same result as removing the INNER scope...?
l

louiscad

11/25/2018, 11:39 AM
I'm not sure. I think adding a coroutine exception handler would work though
d

dave08

11/25/2018, 11:40 AM
I really don't see why the supervisorScope should crash because of a failing child scope... (I mean concept-wise... not in practice), is this maybe a bug in the implementation?
l

louiscad

11/25/2018, 11:43 AM
Regardless, it's always better to have a local scope when you deal with
async
👍🏼 1
d

dave08

11/25/2018, 11:46 AM
And just be aware that it won't help by supervisors...
l

louiscad

11/25/2018, 1:14 PM
Yes. The only place where I currently use
SupervisorJob()
is in LifecycleOwners, and ViewModels (for Android apps) so a coroutine can be cancelled without preventing new ones from being launched afterwards
👍🏼 1
3 Views