Hi, I have a question about the interaction betwee...
# coroutines
j
Hi, I have a question about the interaction between limitedParallelism coroutine scope with launch(start = CoroutineStart.UNDISPATCHED). I have a coroutine scope that is set to limitedParallelism(1), meaning that only one thread should be able to execute in it at a time. I have a function that launches tasks in this coroutine scope. This launch could be from the thread running in this coroutine scope, or any other thread. What I want is that whenever the task is launched from the same thread running in this coroutine scope, it immediately executes on this thread. But if another thread launches the task, the task will wait to execute until the running thread suspends, in order to respect limitedParallelism(1). Is it correct to use launch(start = CoroutineStart.UNDISPATCHED) to achieve this? Or would CoroutineStart.UNDISPATCHED cause the task to always start executing immediately on the current thread, causing limitedParallelism to no longer be respected?
u
I would guess the latter:
Copy code
UNDISPATCHED
Immediately executes the coroutine until its first suspension point in the current thread similarly to the coroutine being started using Dispatchers.Unconfined. However, when the coroutine is resumed from suspension it is dispatched according to the CoroutineDispatcher in its context.
https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-start/-u-n-d-i-s-p-a-t-c-h-e-d/
j
Yeah, this part of the documentation is what is confusing me. It seems to imply that it would always run the code immediately and thus not respect limitedParallelism. But then limitedParallelism also documents this:
The resulting view uses the original dispatcher for execution, but with the guarantee that no more than parallelism coroutines are executed at the same time.
Since it's a "guarantee" that only 1 coroutine (in this case) can execute at the same time, it shouldn't be possible for something like CoroutineStart.UNDISPATCHED to break this guarantee. So which documentation is wrong? 😵‍💫
u
well, the guarantee is for the dispatcher. but your coroutine will not run on that dispatcher (at first). So the guarantee does not apply. Seems consistent. both are right.
j
Ah, alright, this makes sense. In that case is there a way to check whether I am currently already executing in that coroutine scope, and only use CoroutineStart.UNDISPATCHED if this is true?
u
what exactly are you trying to achieve with the guarantee? Are you aware, that
the guarantee that no more than parallelism coroutines are executed at the same time.
does not mean, that one coroutine waits for the other to finish, but only for the other to suspend?
j
or I don't even need to use UNDISPATCHED, I can just execute the code block directly if I am sure I am already in the coroutine scope.
^^ Yes that's what I am trying to achieve. I am trying to use single thread data structures safely with everything that executes in this coroutine. Kind of like Node.JS - when the code suspends, it can switch to a different coroutine to execute
u
Meaning, if you fire 10 async network requests, they will still be executed in parallel
which does not automatically give you thread safety
j
Yeah, I only need the guarantee that only 1 thread can access specific objects at once
u
ok
j
For this problem, it's mainly an issue of optimization. I think I might need to refactor some other parts of my code instead to keep track of whether I am already in a particular coroutine scope. What I am trying to do is to be able to execute "dynamic" functions that can run on different threads/coroutine scopes and call each other, but if a function is called from the same coroutine scope it is supposed to execute, it can run directly, and otherwise it launches a task on that coroutine scope
For now I will just call the coroutine task the normal way which means the "run directly" part doesn't apply for now