Daniel Pitts
12/12/2023, 8:37 PMqueueLock.withLock {
val oldQueue = queue
queue = mutableListOf()
oldQueue
}.forEach { it() }
Casey Brooks
12/12/2023, 8:40 PMMutableStateFlow
, this snippet is equivalent: stateFlow.getAndUpdate { mutableListOf() }
. getAndUpdate is atomic (so you don’t need a lock), and it returns the previous value. updateAndGet is similar, but it returns the new value insteadDaniel Pitts
12/12/2023, 8:43 PMqueueLock
itself protects not just the queue
field, but the contents of the queue. Adding to the queue might run into a race condition.Daniel Pitts
12/12/2023, 8:43 PMqueueLock.withLock {
if (queue.isEmpty()) {
notifyEventLoop()
}
queue.add(block)
}
Daniel Pitts
12/12/2023, 8:45 PMCasey Brooks
12/12/2023, 8:47 PMMutableList
), and only update it with stateFlow.update { }
.
Alternatively, it looks like you’re trying to basically build an async queue, so maybe using a Channel would be better than managing the queue yourself. Conceptually, that’s exactly what a Channel is designed to do, allow any thread to send jobs to it, but safely process the items one at a time in the order they were sentDaniel Pitts
12/12/2023, 8:50 PMDaniel Pitts
12/12/2023, 8:50 PMDaniel Pitts
12/12/2023, 8:57 PMqueue.updateAndGet {
if (it == null) {
notifyEventLoop()
}
QueueNode(block, it)
}
and
generateSequence(queue.getAndUpdate { null }) { it.next }
.map { it.action }
.toList()
.asReversed()
.forEach { it() }
Daniel Pitts
12/12/2023, 8:59 PMDaniel Pitts
12/12/2023, 9:06 PM