https://kotlinlang.org logo
Title
e

Exerosis

02/17/2022, 6:29 AM
class Test<Value> {
    val listeners = ArrayList<suspend (Value) -> (Unit)>()
    val queue = ArrayDeque<() -> (Unit)>()

    suspend fun fire(value: Value) = suspendCoroutine<Unit> { continuation ->
        synchronized(queue) {
            if (queue.isEmpty()) {
                for (listener in listeners)
                    listener(value)
                continuation.resume(Unit)
                while (queue.isNotEmpty())
                    queue.removeLast()()
            } else {
                queue.add {
                    for (listener in listeners)
                        listener(value)
                    continuation.resume(Unit)
                }
                COROUTINE_SUSPENDED
            }
        }
    }
    fun listen(listener: suspend (Value) -> (Unit)) {
        listeners += listener
    }
}
If I have something along these lines, I know this isn't entirely valid... but the idea is that you fire an event and all the listeners should be fired with the given value before any of them are fired with a new value from elsewhere. Would it be possible to detect when a listener fires "recursively" for example:
test.listen { if (it <= 0) test.fire(50) }
And then instead of deadlocking, simply leave that listener "partially executed" and move to the next one until all of the listeners have had a chance to see the first value... then fire this recursively changed value out... then finish executing the partially executed listener... and finally if any other changes were pushed out concurrently elsewhere they would be fired. Ik this is a confusing question, but I figured the only way I could get close to this functionallity was by using continuatons.
n

Nick Allen

02/17/2022, 8:23 AM
If you add values to a
Channel
, then you can read from it with a single coroutine and send each value to all the listeners.