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

christophsturm

01/30/2021, 10:16 AM
if i have a list of 10 deferreds, is there an easy way each one of them as soon as it completes?
deferredList.mapResolved{deferredResult -> ... }
if i do it like this, is there a way to be sure that my launch blocks don’t interrupt each other? I want my println output not to be mixed up by threads
Copy code
suspend fun bla(deferred: List<Deferred<Context>>) {
    coroutineScope {
        deferred.forEach {
            launch {
                val context = it.await()
                println(
                    context.summary()
                )
            }
        }
        
    }
    
}
a

Arslan Armanuly

01/30/2021, 1:57 PM
if you want the several printlns behave as if they were called from the one thread, you can create
Copy code
val singleThreadedContext = Executors.newSingleThreadExecutor().asCoroutineDispatcher()
and then
Copy code
withContext(singleThreadedContext) {
    println(context.summary())
}
c

christophsturm

01/30/2021, 2:27 PM
Great. Will that perform better than to make the Println synchronized on context?
a

Arslan Armanuly

01/30/2021, 3:49 PM
I would recommend not using synchronized with coroutines because coroutines works on the concept of continuations and if you have suspending function call in the synchronized block, it can have undesirable behaviour
If you want the behaviour that synchronized provides, you can use
Copy code
val mutex = Mutex()
mutex.withLock { /* code */ }
If you want to know more about sharing mutable state, here is great article on https://kotlinlang.org/docs/reference/coroutines/shared-mutable-state-and-concurrency.html
c

christophsturm

01/30/2021, 5:36 PM
hmm, but whats better? a task switch or a mutex? I guess the mutex will perform better. will the await change the dispatcher to the one where the deferred was resolved, or will it stay in the dispatcher of my async block?
z

Zach Klippenstein (he/him) [MOD]

01/30/2021, 5:36 PM
if i do it like this, is there a way to be sure that my launch blocks don’t interrupt each other?
You mean you want the prints to be executed in the order of the list, regardless of which order the deferreds complete in?
c

christophsturm

01/30/2021, 5:39 PM
I don’t even care about the order. i just want just one println to run at a time
each deferred is a result, the order does not matter
z

Zach Klippenstein (he/him) [MOD]

01/30/2021, 5:40 PM
The code you wrote will definitely do that. And it will also do so in the same order, that of the list, every time. There’s no magic going on here.
c

christophsturm

01/30/2021, 5:41 PM
well it will print each result as soon as the deferred is ready
z

Zach Klippenstein (he/him) [MOD]

01/30/2021, 5:41 PM
The first iteration of the loop waits for the first deferred to complete. It doesn’t wait for or know about any of the other deferreds. Only when the first deferred completes, then the print, then the next deferred is awaited on, etc
c

christophsturm

01/30/2021, 5:41 PM
if they all are already ready it will be the order of the list
z

Zach Klippenstein (he/him) [MOD]

01/30/2021, 5:41 PM
Oh derp I missed the launch
Ok then the mutex solution makes sense. Although you could also convert your deferreds to Flows and use the merge operator
You could also create a channel, then from your launched coroutines send the results into the channel, and in your main coroutine, receive from the channel in a loop
c

christophsturm

01/30/2021, 5:45 PM
it was a channel at some point then i converted it to a list of deferreds
but now i want to print the deferreds as soon as they are ready so maybe deferreds are not the best solution anymore
z

Zach Klippenstein (he/him) [MOD]

01/30/2021, 5:46 PM
What’s your producer code look like?
right now contextExecutor returns a list of deferred (one for each test context). and those each contain a list of deferred for each test result. and I’m now printing the results for each context when all the test of that context are finished
so its a bit more complicated than my example
z

Zach Klippenstein (he/him) [MOD]

01/30/2021, 8:05 PM
Hm, I don’t think anything there requires syncrhonization. You have a single print call per launched coroutine, and i believe print is effectively atomic on most systems.
that
asSequence()
call on
contextInfos
looks redundant though,
List
has
forEach
as well
c

christophsturm

01/30/2021, 10:03 PM
i guess if println is not guaranteed to be atomic i can just wrap it with a mutex anyway
2 Views