diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/cache/ExpiringLruCache.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/cache/ExpiringLruCache.kt index a72c1061d..2a54236dc 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/cache/ExpiringLruCache.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/cache/ExpiringLruCache.kt @@ -1,6 +1,6 @@ package org.koitharu.kotatsu.core.cache -import androidx.collection.SieveCache +import org.koitharu.kotatsu.core.util.SynchronizedSieveCache import org.koitharu.kotatsu.parsers.model.MangaSource import java.util.concurrent.TimeUnit import org.koitharu.kotatsu.core.cache.MemoryContentCache.Key as CacheKey @@ -11,9 +11,8 @@ class ExpiringLruCache( private val timeUnit: TimeUnit, ) { - private val cache = SieveCache>(maxSize) + private val cache = SynchronizedSieveCache>(maxSize) - @Synchronized operator fun get(key: CacheKey): T? { val value = cache[key] ?: return null if (value.isExpired) { @@ -24,27 +23,21 @@ class ExpiringLruCache( operator fun set(key: CacheKey, value: T) { val value = ExpiringValue(value, lifetime, timeUnit) - synchronized(this) { - cache.put(key, value) - } + cache.put(key, value) } - @Synchronized fun clear() { cache.evictAll() } - @Synchronized fun trimToSize(size: Int) { cache.trimToSize(size) } - @Synchronized fun remove(key: CacheKey) { cache.remove(key) } - @Synchronized fun removeAll(source: MangaSource) { cache.removeIf { key, _ -> key.source == source } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/util/SynchronizedSieveCache.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/SynchronizedSieveCache.kt new file mode 100644 index 000000000..09b10e494 --- /dev/null +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/util/SynchronizedSieveCache.kt @@ -0,0 +1,36 @@ +package org.koitharu.kotatsu.core.util + +import androidx.collection.SieveCache + +class SynchronizedSieveCache( + private val delegate: SieveCache, +) { + + constructor(maxSize: Int) : this(SieveCache(maxSize)) + + private val lock = Any() + + operator fun get(key: K): V? = synchronized(lock) { + delegate[key] + } + + fun put(key: K, value: V): V? = synchronized(lock) { + delegate.put(key, value) + } + + fun remove(key: K) = synchronized(lock) { + delegate.remove(key) + } + + fun evictAll() = synchronized(lock) { + delegate.evictAll() + } + + fun trimToSize(maxSize: Int) = synchronized(lock) { + delegate.trimToSize(maxSize) + } + + fun removeIf(predicate: (K, V) -> Boolean) = synchronized(lock) { + delegate.removeIf(predicate) + } +} diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/domain/EdgeDetector.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/domain/EdgeDetector.kt index 76cb60e57..7b6c34de1 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/domain/EdgeDetector.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/domain/EdgeDetector.kt @@ -6,7 +6,6 @@ import android.graphics.Color import android.graphics.Point import android.graphics.Rect import androidx.annotation.ColorInt -import androidx.collection.SieveCache import androidx.core.graphics.alpha import androidx.core.graphics.blue import androidx.core.graphics.get @@ -23,13 +22,14 @@ import kotlinx.coroutines.runInterruptible import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.withContext +import org.koitharu.kotatsu.core.util.SynchronizedSieveCache import org.koitharu.kotatsu.core.util.ext.use import kotlin.math.abs class EdgeDetector(private val context: Context) { private val mutex = Mutex() - private val cache = SieveCache(CACHE_SIZE) + private val cache = SynchronizedSieveCache(CACHE_SIZE) suspend fun getBounds(imageSource: ImageSource): Rect? { cache[imageSource]?.let { rect ->