Leon K
02/21/2020, 2:18 PMsuspend fun and a non-suspending function. I cannot just do @Synchronized on the blocking one and use Mutex on the suspend-one as these don't exclude each other, such that there is still the posibility of two concurrent accesses.
It seems as tough Mutex is not usable from non-blocking code, and @Synchronized doesn't help with `suspend fun`s.
what's the best approach here?diesieben07
02/21/2020, 2:44 PMMutex inside runBlocking to achieve an effect similar to @Synchronized (block instead of suspend when waiting for the lock).Leon K
02/21/2020, 2:45 PMuli
02/21/2020, 2:47 PMLeon K
02/21/2020, 2:48 PMrunBlocking to somehwere else...Zach Klippenstein (he/him) [MOD]
02/21/2020, 2:53 PMAtomicReference and not deal with locking at all.Leon K
02/21/2020, 2:54 PMLeon K
02/21/2020, 2:57 PMAtomicReference a suspend (T) -> T? otherwise this would only solve my non-suspending case, which is only half my use-case ;DZach Klippenstein (he/him) [MOD]
02/21/2020, 2:59 PMArkadii Ivanov
02/21/2020, 3:01 PMsynchronized {} block. Just don't suspend inside the block.Leon K
02/21/2020, 3:02 PMclass ExpirationBasedCache<V>(private val expirationTimeSeconds: Long) {
@Volatile
private var cacheData: Pair<Long, V>? = null
private val mutex = Mutex()
/** Read the value from the cache if it exists and is not expired,
* otherwise calculate a new value using the given [function][f]. */
fun getValueBy(f: suspend () -> V): V = runBlocking { getValueBySuspending(f) }
/** Read the value from the cache if it exists and is not expired,
* otherwise calculate a new value using the given [function][f]. */
suspend fun getValueBySuspending(f: suspend () -> V): V = mutex.withLock {
cacheData
?.takeIf { (timeOfCache, _) -> System.currentTimeMillis() - timeOfCache < expirationTimeSeconds * 1000 }
?.second
?: f().also { cacheData = Pair(System.currentTimeMillis(), it) }
}
}
because this cache should be accessible from both suspending and non-suspending contexts, I need to support both.
The idea is that, if one thread is currently calculating the value, others don't start doing the same thing but wait for the first thread and then reuse it's result.Leon K
02/21/2020, 3:09 PMsynchronized is not an option as i DO need to suspend within the blockArkadii Ivanov
02/21/2020, 3:10 PMsupend fun get() and fun getBlocking() The last one will call the first under runBlocking block. And use Mutex.Leon K
02/21/2020, 3:11 PM