https://kotlinlang.org logo
Title
e

Eric Womer

01/25/2023, 9:11 PM
How do you code doing 16 jobs 51 asyncs/launches with a for loop and the many not get messed up?
u

uli

01/27/2023, 1:38 PM
Hi @Eric Womer did you read and understand @Sam’s answer? https://kotlinlang.slack.com/archives/C1CFAFJSK/p1674648841566549?thread_ts=1674647885.585549&cid=C1CFAFJSK I’d suggest first fixing that and then trying again. If you need help in understanding or fixing the race condition, feel free to ask.
e

Eric Womer

01/27/2023, 1:43 PM
@uli Basically I need to get the out put as a var, probably a list, from the deferred, correct?
So my theory was right that it was running multiple asyncs with the same data, like several of them had the starting value 17 instead of the series I was trying to create?
u

uli

01/27/2023, 1:53 PM
looked a bit at your code. and not sure what you are trying to do… you want to do 826 iterations and let’s say, you have 4 cores. Then you would start 826/4=206 jobs? I would expect you want to start 4 jobs with 206 iterations each.
e

Eric Womer

01/27/2023, 1:54 PM
I rewrote it that way yes, but for me in android stuidio it was 16 cores so 16 jobs 51 iterations and one last iteration of 10 (the remainder)
u

uli

01/27/2023, 1:55 PM
no. 51 jobs, 16 iterations
e

Eric Womer

01/27/2023, 1:55 PM
The 826 are ids that need to be passed to a method.
I flipped the math around, I thought it was silly to have the inner for loop only iterate 16 times, and create 51 jobs.
u

uli

01/27/2023, 1:56 PM
ah, corect
e

Eric Womer

01/27/2023, 1:56 PM
so the outside for loop would go 16 loops, and the inner would do 51
I wanted top put 51 iterations into the async so I could divide up the network call into several threads* all while having a valid counter to keep track of the ids already gotten.
u

uli

01/27/2023, 1:58 PM
So the 1st issue is that your upper bound in this for loop
for (j in i..forCount) {
changes while the loop still itterates.
e

Eric Womer

01/27/2023, 1:58 PM
yup
u

uli

01/27/2023, 2:00 PM
This can be fixed like this:
val upperBound = forCount
async(Dispatchers.Default) {
  for (j in i..upperBound) {
e

Eric Womer

01/27/2023, 2:00 PM
Would that work, when forCount is still being changed?
u

uli

01/27/2023, 2:01 PM
After that you will probably run into an issue with concurrent list modification. So yes, you need to return the lists as the deferred from async and then join the partial lists
e

Eric Womer

01/27/2023, 2:02 PM
yeah, through an theList.add(defferedList.await() /* or would it be awaitAll()? *?)
u

uli

01/27/2023, 2:14 PM
This can be done very elegant with a map/fold instead of a for loop along these lines:
(1 .. (count - remainder) step cores).map { i-> 
  ...
  ...
  async { 
    // innerLoop
  }
}.awaitAll().flatten()
And it might be mathematically easier to count through the number of jobs and then calculate the indices belonging to the job:
(0 until cores).map { core->
  async {
    val i0 = quotent * core
    val i1 = quotent * (core + 1) - 1
    ...
  }
}
e

Eric Womer

01/27/2023, 2:29 PM
So manually add each individual call to the async block?