Browse Source
Before the fix we could cancel a coroutine and the cancelled deferred was saved in cache. ## Release Notes ### Fixes - Resources - _(prerelease fix)_ Fix a cached empty resource on a Compose for Web if the resource loading was canceled during progresspull/4820/head
Konstantin
6 months ago
committed by
GitHub
4 changed files with 57 additions and 64 deletions
@ -0,0 +1,31 @@ |
|||||||
|
package org.jetbrains.compose.resources |
||||||
|
|
||||||
|
import kotlinx.coroutines.CoroutineStart |
||||||
|
import kotlinx.coroutines.Deferred |
||||||
|
import kotlinx.coroutines.async |
||||||
|
import kotlinx.coroutines.coroutineScope |
||||||
|
import kotlinx.coroutines.sync.Mutex |
||||||
|
import kotlinx.coroutines.sync.withLock |
||||||
|
|
||||||
|
internal class AsyncCache<K, V> { |
||||||
|
private val mutex = Mutex() |
||||||
|
private val cache = mutableMapOf<K, Deferred<V>>() |
||||||
|
|
||||||
|
suspend fun getOrLoad(key: K, load: suspend () -> V): V = coroutineScope { |
||||||
|
val deferred = mutex.withLock { |
||||||
|
var cached = cache[key] |
||||||
|
if (cached == null || cached.isCancelled) { |
||||||
|
//LAZY - to free the mutex lock as fast as possible |
||||||
|
cached = async(start = CoroutineStart.LAZY) { load() } |
||||||
|
cache[key] = cached |
||||||
|
} |
||||||
|
cached |
||||||
|
} |
||||||
|
deferred.await() |
||||||
|
} |
||||||
|
|
||||||
|
//@TestOnly |
||||||
|
fun clear() { |
||||||
|
cache.clear() |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue