aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/at/hannibal2/skyhanni/utils/TimeLimitedCache.kt
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/at/hannibal2/skyhanni/utils/TimeLimitedCache.kt')
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/TimeLimitedCache.kt38
1 files changed, 34 insertions, 4 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/TimeLimitedCache.kt b/src/main/java/at/hannibal2/skyhanni/utils/TimeLimitedCache.kt
index 018c858fa..4c96c9b3c 100644
--- a/src/main/java/at/hannibal2/skyhanni/utils/TimeLimitedCache.kt
+++ b/src/main/java/at/hannibal2/skyhanni/utils/TimeLimitedCache.kt
@@ -1,7 +1,9 @@
package at.hannibal2.skyhanni.utils
import com.google.common.cache.CacheBuilder
+import java.util.concurrent.ConcurrentMap
import java.util.concurrent.TimeUnit
+import java.util.concurrent.locks.ReentrantReadWriteLock
import kotlin.time.Duration
class TimeLimitedCache<K : Any, V : Any>(
@@ -9,9 +11,18 @@ class TimeLimitedCache<K : Any, V : Any>(
private val removalListener: (K?, V?) -> Unit = { _, _ -> },
) : Iterable<Map.Entry<K, V>> {
+ private val cacheLock = ReentrantReadWriteLock()
+
private val cache = CacheBuilder.newBuilder()
.expireAfterWrite(expireAfterWrite.inWholeMilliseconds, TimeUnit.MILLISECONDS)
- .removalListener { removalListener(it.key, it.value) }
+ .removalListener {
+ cacheLock.writeLock().lock()
+ try {
+ removalListener(it.key, it.value)
+ } finally {
+ cacheLock.writeLock().unlock()
+ }
+ }
.build<K, V>()
// TODO IntelliJ cant replace this, find another way?
@@ -27,11 +38,30 @@ class TimeLimitedCache<K : Any, V : Any>(
fun remove(key: K) = cache.invalidate(key)
- fun entries(): Set<Map.Entry<K, V>> = cache.asMap().entries
+ fun entries(): Set<Map.Entry<K, V>> = getMap().entries
+
+ fun values(): Collection<V> = getMap().values
+
+ fun keys(): Set<K> = getMap().keys
- fun values(): Collection<V> = cache.asMap().values
+ /**
+ * Modifications to the returned map are not supported and may lead to unexpected behavior.
+ * This method is intended for read-only operations such as iteration or retrieval of values.
+ *
+ * @return A read-only view of the cache's underlying map.
+ */
+ private fun getMap(): ConcurrentMap<K, V> {
+ val asMap: ConcurrentMap<K, V>
- fun keys(): Set<K> = cache.asMap().keys
+ cacheLock.readLock().lock()
+ try {
+ asMap = cache.asMap()
+ } finally {
+ cacheLock.readLock().unlock()
+ }
+
+ return asMap
+ }
fun containsKey(key: K): Boolean = cache.getIfPresent(key) != null