Ayfri
12/06/2021, 6:19 AMZach Klippenstein (he/him) [MOD]
12/06/2021, 6:49 AMAyfri
12/06/2021, 12:36 PMJoffrey
12/06/2021, 12:46 PMcoroutineScope { .. }
and use multiple launch
inside that do the computation you need. If you call all of this on a multithreaded dispatcher like Dispatchers.Default
, those coroutines will run in parallelAyfri
12/06/2021, 12:54 PMJoffrey
12/06/2021, 12:55 PMAyfri
12/06/2021, 1:19 PMJoffrey
12/06/2021, 1:20 PMAyfri
12/06/2021, 1:22 PMJoffrey
12/06/2021, 1:25 PMchunked()
for instance, and passing a chunk to a coroutine). So you can for sure do that.
Yet another option is to use a Channel
and spawn the number of coroutines you want to process that channel.Ayfri
12/06/2021, 1:27 PMJoffrey
12/06/2021, 1:29 PMsend
elements (send
is suspending, and it suspends when the buffer is full), and other coroutines can receive elements from the channel.
If many coroutines iterate on the same channel, the elements will be sent to them in a fan-out fashion, meaning that each item will only be sent to one of the consuming coroutines (so it's what you want).fun distance(img1: Image, img2: Image): Long = TODO()
You could write this:
// returns null if the list is empty, you could also throw an exception instead
suspend fun findClosestImageOrNull(src: Image, candidates: List<Image>): Image? {
// you can also define this helper class outside the function if needed elsewhere
data class MeasuredCandidate(val img: Image, val distance: Long)
val measuredCandidates = coroutineScope {
candidates
.map { candidate ->
async { MeasuredCandidate(candidate, distance(src, candidate)) }
}
.awaitAll()
}
return measuredCandidates.minByOrNull { it.distance }?.img
}
This defines the computation in a concurrent way. If you want to run this in parallel, simply run findClosestImageOrNull
in a multi-threaded dispatcher such as `Dispatchers.Default`:
suspend fun main() {
withContext(Dispatchers.Default) {
findClosestImageOrNull(...)
}
}
You could also replace coroutineScope
with withContext(Dispatchers.Default)
right inside findClosestImageOrNull
, but this prevents the caller from choosing another dispatcher (e.g. in tests).
That said, because the distance
function is not suspending, the coroutines will be run sequentially if you run this function on a single-threaded dispatcher, so choosing a good dispatcher inside the function might avoid mistakes on the calling side. Up to you!Ayfri
12/06/2021, 10:42 PM