dave08
10/18/2018, 2:21 PMsupervisorScope { }
and coroutineScope { }
get their CoroutineScope
from?marstran
10/18/2018, 2:23 PMdave08
10/18/2018, 2:24 PMThe provided scope inherits its [coroutineContext][CoroutineScope.coroutineContext] from the outer scope, but overrides context's [Job] with [SupervisorJob].
...?CoroutineScope
does it automatically inherit the GlobalScope
? Also does it have any default Dispatcher?SiebelsTim
10/18/2018, 2:28 PMdave08
10/18/2018, 2:31 PMfrom the outer scope
in the kdocs, is really just an assumption that we are running from one, otherwise, it could be a runBlocking
or GlobalScope
... so it gets cancelled along with wherever the suspend function was called from, right?SiebelsTim
10/18/2018, 2:54 PMcoroutineScope
is a suspend fun
, therefore it can only be called from a suspending function. Every suspending functions has an implicit Continuation and therefore a CoroutineContext
. This CoroutineContext
is used. So when you are using coroutineScope {}
within a coroutine that was launched on GlobalScope
, the new scope will inherit `GlobalScope`'s context.dave08
10/18/2018, 2:59 PMCoroutineScope
the suspend fun
is being called from). Thanks a lot, this is now much clearer!Vsevolod Tolstopyatov [JB]
10/18/2018, 3:19 PMcoroutineContext
, not the scope. CoroutineScope
is a wrapper around coroutineContext
, which is created by builders. It does not matter whether you have outer scope or not, because coroutineContext
is always present in suspend functions.
Also does it have any default Dispatcher?No. Which dispatcher is used depends on particular primitive. E.g. for most of our builders (
async
, launch
, produce
etc.) Dispatchers.Default
will be used if context does not have one.dave08
10/18/2018, 3:28 PMlaunch
called from a suspend function could be Dispatchers.Default
or inherit a parent's dispatcher far back in the call stack... so if one would call it from runBlocking
or GlobalScope
it would work on Dispatchers.Default
but from a presenter running on Dispatchers.Main
inheriting from the Presenter's CoroutineScope
..., shouldn't this be a bit more explicit? @Vsevolod Tolstopyatov [JB]Vsevolod Tolstopyatov [JB]
10/18/2018, 3:55 PMor inherit a parent’s dispatcher far back in the call stack...It cannot happen “out of thin air”. You have precise control over what happens: 1) You can use
coroutineScope
. Then you are using convention “here is my isolated scope with dispatcher inherited from the caller”.
2) You can make your method extension on coroutine scope. Then again you are opt-in for “caller is responsible”
3) You can use withContext(dispatcher)
, then you are forcing dispatcher you want
4) Your API requires dispatcher in parameters and/or you are always pass it explicitly such as fun CoroutineScope.launchInIO = async(IO) { ... }
shouldn’t this be a bit more explicitWe are always open for a better proposals 🙂 But explicitly requiring dispatcher in every builder is too verbose. The idea of structured concurrency is that once you have a scope, all coroutines inherit it and optionally override some parts of context.
dave08
10/18/2018, 4:05 PMDispatchers.Default
to be used like it used to be before structured concurrency.. or someone migrating to structured concurrency might not notice that instead of defaulting to something similar to CommonPool
it gets inherited from the scope ... which could be completely wrong... maybe some kind of migration guide or stress in the docs along with a link to it from the release notes (that I assume is usually what most people look at...).coroutineScope
and supervisorScope
builders as if one used withContext
?launch
or async
...Vsevolod Tolstopyatov [JB]
10/18/2018, 4:53 PMto allow to override the Dispatcher in thecoroutineScope
withContext(dispatcher)
🙂
the api provider expects the defaultDispatchers.Default
That way, the entry point doesn’t make any assumptionsif you expect it — specify it explicitly. Nothing in API prevents you from that. You can use
withContext(Dispatcher)
or create CoroutineScope(coroutineContext + dispatcher)
and use it as receiver etc.coroutine-guide.md
🙂
I’d happy to have your questions in this F.A.Q if you’ll make them short and concretedave08
10/18/2018, 7:20 PMlaunch
(parts) and async
(file received) and produce
(for download progress) spread out in all those classes. It comes out that I have a few `coroutineScope`s spread out all over, those are internal, so they can inherit a dispatcher. But the entrypoints need to be explicit, so if there would be coroutineScope(<http://Dispatchers.IO|Dispatchers.IO>) { }
for those endpoints, anyone using this library even from the main thread would be fine, and to the implementor it's clearer and more explicit than coroutineScope { withContext(<http://Dispatchers.IO|Dispatchers.IO>) { } }
. Both forms are needed, no?