util.Cache.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of experiment-jvm-server Show documentation
Show all versions of experiment-jvm-server Show documentation
Amplitude Experiment server-side SDK for JVM (Java, Kotlin)
The newest version!
package com.amplitude.experiment.util
import java.util.HashMap
/**
* Least recently used (LRU) cache with TTL for cache entries.
*/
internal class Cache(private val capacity: Int, private val ttlMillis: Long = 0) {
private class Node(
var key: K? = null,
var value: V? = null,
var prev: Node? = null,
var next: Node? = null,
var ts: Long = System.currentTimeMillis(),
)
private var count = 0
private val map: MutableMap?> = HashMap()
private val head: Node = Node()
private val tail: Node = Node()
private val lock = Any()
private val timeout = ttlMillis > 0
init {
head.next = tail
tail.prev = head
}
operator fun get(key: K): V? = synchronized(lock) {
val n = map[key] ?: return null
if (timeout && n.ts + ttlMillis < System.currentTimeMillis()) {
remove(key)
return null
}
updateInternal(n)
return n.value
}
operator fun set(key: K, value: V) = synchronized(lock) {
var n = map[key]
if (n == null) {
n = Node(key, value)
map[key] = n
addInternal(n)
++count
} else {
n.value = value
n.ts = System.currentTimeMillis()
updateInternal(n)
}
if (count > capacity) {
val del = tail.prev?.key
if (del != null) {
remove(del)
}
}
}
fun remove(key: K): Unit = synchronized(lock) {
val n = map[key] ?: return
removeInternal(n)
map.remove(n.key)
--count
}
private fun updateInternal(node: Node) {
removeInternal(node)
addInternal(node)
}
private fun addInternal(node: Node) {
val after = head.next
head.next = node
node.prev = head
node.next = after
after!!.prev = node
}
private fun removeInternal(node: Node) {
val before = node.prev
val after = node.next
before!!.next = after
after!!.prev = before
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy