I have tasks coming in, and I want to start a coro...
# coroutines
m
I have tasks coming in, and I want to start a coroutine for each so they can be worked on in parallel, however I need to return them in the same order they come in, so if a later one is finished first it should wait before getting returned until the previous ones finish. What would be the best concept / mechanism to achieve that?
j
You can use a concurrent map:
Copy code
suspend fun <T, R> List<T>.concurrentMap(transform: (T) -> R): List<R> = coroutineScope {
    map { async { transform(it) }}.awaitAll()
}
If you call this suspend fun in a coroutine scope that has a multi-threaded dispatcher, it will effectively run in parallel.
You could also enforce this by swapping
coroutineScope
with
withContext(Dispatchers.Default)
(or IO, or another multi-threaded dispatcher)
m
Hmm, yes but I don't have the list of tasks ahead of time, they come one by one, at any time.
They are just function calls, and I need to ensure a later function call doesn't return before an earlier one.
j
Doesn't return.. a value? or doesn't return at all?
m
Anything really, could be a callback, could be updating a flow, doesn't matter as long as I can get the results in the same order the requests came in.
j
What I mean is that, if they don't return results and only have side effects, then it's unclear what you mean by "they should not return before an earlier one". If one of the task updates some state as a side effect but doesn't return any result, what does it mean to run it in parallel of other tasks, but have its result in the correct order relative to others?
If your tasks return values, then talking about ordering results makes sense. And in that case you could just start the processing under
async
and store the `Deferred`s, in the order they were enqueued, in a list of sorts. Then you can
await()
them in order.
m
A list of
Deferred
would indeed do what I want! Thanks again. 😄
👍 2
j
You're welcome