Stefan Oltmann
09/29/2023, 7:54 AMdelay
👀...
I want a fixed amount of coroutines working on my job and I have high priority requests that should be worked on first and low priority requests that can be done later.
I don't think my implementation is good.
What would be a good implementation of my goal here?
It must be Multiplatform.
private val CONCURRENT_WORKERS = PROCESSOR_COUNT * 2
private val WORKER_COROUTINE_SCOPE = CoroutineScope(Dispatchers.Default)
private val channel = Channel<Pair<Photo, CompletableDeferred<PhotoMetadata>>>()
private val queue = ArrayDeque<Pair<Photo, CompletableDeferred<PhotoMetadata>>>()
private val mutex = Mutex()
init {
/**
* Run as many coroutines for parallel execution as we need.
*/
repeat(CONCURRENT_WORKERS) {
WORKER_COROUTINE_SCOPE.launch(CoroutineName("MetadataReader-$it")) {
for (work in channel)
readAndSaveMetadataInternal(work)
}
}
/**
* This coroutine gets the next photo from the list and sends
* it to the channel.
*/
WORKER_COROUTINE_SCOPE.launch(CoroutineName("MetadataReaderFeeder")) {
while (true) {
val next = mutex.withLock { queue.removeFirstOrNull() }
/* Nothing to do right now. Check back later. */
if (next == null) {
delay(500)
continue
}
channel.send(next)
}
}
}
override suspend fun readAndSaveMetadata(photo: Photo, withPriority: Boolean): PhotoMetadata {
val deferred = CompletableDeferred<PhotoMetadata>()
mutex.withLock {
if (withPriority)
queue.addFirst(photo to deferred)
else
queue.addLast(photo to deferred)
}
return deferred.await()
}
Sam
09/29/2023, 8:07 AMselect
to receive from both channels at once, giving preference to the high-priority channel.Stefan Oltmann
09/29/2023, 8:11 AMselect
is biased in priority towards the first call. There is also a selectUnbiased
. So that's what I wanted. Thank you again.