https://kotlinlang.org logo
#getting-started
Title
# getting-started
d

Daniel Pitts

12/12/2023, 8:37 PM
Is there maybe a better way to write this:
Copy code
queueLock.withLock {
    val oldQueue = queue
    queue = mutableListOf()
    oldQueue
}.forEach { it() }
c

Casey Brooks

12/12/2023, 8:40 PM
If you manage the queue in a
MutableStateFlow
, 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 instead
d

Daniel Pitts

12/12/2023, 8:43 PM
the
queueLock
itself protects not just the
queue
field, but the contents of the queue. Adding to the queue might run into a race condition.
The enqueue method is basically like this:
Copy code
queueLock.withLock {
    if (queue.isEmpty()) {
        notifyEventLoop()
    }
    queue.add(block)
}
This is specifically in JVM if that makes a difference.
c

Casey Brooks

12/12/2023, 8:47 PM
Then you’d want to use a read-only list in the StateFlow (not
MutableList
), 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 sent
d

Daniel Pitts

12/12/2023, 8:50 PM
Hmm, interesting ideas. I'm not sure Channel actually helps in this case, since there won't be a coroutine context.
Though the stateFlow idea makes me think maybe a simple linked-list implementation could work, and the just using the head for the state.
Copy code
queue.updateAndGet {
    if (it == null) {
        notifyEventLoop()
    }
    QueueNode(block, it)
}
and
Copy code
generateSequence(queue.getAndUpdate { null }) { it.next }
    .map { it.action }
    .toList()
    .asReversed()
    .forEach { it() }
Thanks @Casey Brooks, I appreciate the discussion!
Hmm, I think I want to use AtomicReference rather than MutableStateFlow, since I wanted to make this piece independent from coroutines. The code looks the same though, luckily.
2 Views