https://kotlinlang.org logo
Title
l

Luis Munoz

06/09/2020, 9:17 PM
In this code will the fist collect finish before the second collect is started or is possible that the execution will interleave?
val singleThread =   newSingleThreadContext("SingleThread")
val flow = flow { 
 emit("a")
 blocking call
 delay(1000)
 emit("b")
}.flowOn(singleThread)

launch(<http://Dispachers.IO|Dispachers.IO>) {
    flow.collect {
        println(it)
    }
}
launch(<http://Dispachers.IO|Dispachers.IO>)  { 
    flow.collect {
            println(it)
    }
}
o

octylFractal

06/09/2020, 9:18 PM
interleaving is impossible here because the collects are linear, one must finish before the other can even be called
if you were to launch them separately, then I would say that they could interleave
l

Luis Munoz

06/09/2020, 9:20 PM
this is what makes coroutines so difficult to work with I can't be sure if they will interleave or not if I lauch them separately, is this documented anywhere or how am I to verify this?
o

octylFractal

06/09/2020, 9:23 PM
why is it difficult to work with if launched separately? it's like asking "if I start two programs, will one finish before the other" -- obviously you can't know the answer, they're executed concurrently, not in any ordered way
if you want them to be ordered, you must place some sort of ordering guarantee, otherwise, you cannot assume they are ordered, as you asked for concurrency by using two separate coroutines
☝️ 1
l

Luis Munoz

06/09/2020, 9:25 PM
it adds another dimension to shared mutable state. here I have 1 thread so I know I can share mutable state between coroutines. I just can't tell when they overlap because the scheduling of the coroutines is not documented or obvious in anyway
o

octylFractal

06/09/2020, 9:26 PM
I don't think they should document the scheduling, I don't even know if they can deterministic-ally say when one will switch to the other. That's partially up to the OS you're running on to pick which threads to run
l

Luis Munoz

06/09/2020, 9:27 PM
my execution is on 1 thread
nothing to do with os
o

octylFractal

06/09/2020, 9:27 PM
no, you're launching on the IO dispatchers
`collect`'s block will be running on the IO threads
l

Luis Munoz

06/09/2020, 9:28 PM
oh true so it seems that it must switch between the collects if they suspend
o

octylFractal

06/09/2020, 9:29 PM
basically, yes. if one isn't doing work, the other can run -- this even applies to that
delay
you have in the single-thread section, that can allow the other flow to start processing, because the thread is available for executing work
l

Luis Munoz

06/09/2020, 9:29 PM
.flowOn(singleThread)
code that runs can only be in 1 thread though
so I should be able to share state
o

octylFractal

06/09/2020, 9:30 PM
flowOn
only affects code prior to that call -- you can use e.g. HashMap safely, but you may not assume that the block runs to completion before another one starts
if you want that, you should probably use
Mutex
to ensure that it can't execute simultaneously (it's basically a suspending lock)
👍 1
r

Rechee Jozil

06/10/2020, 6:38 AM
You are correct that there's no guarantee of execution order of the blocks within those launch calls. They can each be executed on a different thread (within Dispatchers.IO thread pool).
l

Luis Munoz

06/10/2020, 3:14 PM
@Rechee Jozil the order is not the problem the problem is the interleaving