dfriehs
02/13/2020, 1:43 PMclass DelayUntilReady<T>(private val builder: () -> T) {
private companion object {
enum class State { READY, WAIT }
}
private val channel: Channel<Unit> = Channel(0)
private var state: State = State.WAIT
fun setReady() {
state = State.READY
channel.offer(Unit)
}
fun setWait() {
state = State.WAIT
}
suspend fun get(): T {
while (state == State.WAIT) channel.receive()
return builder.invoke()
}
}
object Cache {
private var elements: Map<String, String> = emptyMap()
private val elementAwait = DelayUntilReady { elements }
@Suppress("FunctionName")
suspend fun Elements(): Map<String, String> = elementAwait.get()
fun setupElements(builder: () -> Map<String, String>) {
elementAwait.setWait()
// parse
elements = builder.invoke()
elementAwait.setReady()
}
}
Did I miss something, or is there a better way to write this? Please note that i will have around 4-5 of these caches in the Cache
object, not just one as in the example.Zach Klippenstein (he/him) [MOD]
02/13/2020, 4:28 PMdfriehs
02/14/2020, 9:51 AMclass Container<K, V> {
private var container: Map<K, V> = emptyMap()
private val init: Mutex = Mutex()
private val access: Mutex = Mutex().apply { tryLock(init) }
suspend fun initialize(builder: () -> Map<K, V>): Unit = init.withLock {
if (!access.holdsLock(init)) access.lock(init)
container = builder.invoke()
access.unlock(init)
}
suspend fun invalidate(): Unit = init.withLock {
if (!access.holdsLock(init)) access.lock(init)
container = emptyMap()
}
suspend fun retrieve(key: K): V? = access.withLock(container) { container[key] }
}
Zach Klippenstein (he/him) [MOD]
02/25/2020, 2:46 PM