juliocbcotta
05/03/2023, 8:34 AMMutex
... I am using the mutex in multiple methods... but I am not sure about the behaviour...
private val cache = MutableStateFlow(emptySet<String>())
private val mutex = Mutex()
suspend fun add(brand: Favorite) {
mutex.withLock {
val favorites = cache.value.toMutableSet()
favorites.add(brand.brandId)
cache.emit(favorites.toSet())
}
}
suspend fun remove(brand: Favorite) {
mutex.withLock {
val favorites = cache.value.toMutableSet()
favorites.remove(brand.brandId)
cache.emit(favorites.toSet())
}
}
suspend fun set(favorites: Collection<Favorite>) {
mutex.withLock {
cache.emit(favorites.map { it.brandId }.toSet())
}
}
Can I say that this code is secure from concurrency point of view ? I mean, I am locking the access in different suspended
methods using the same mutex
.Tijl
05/03/2023, 8:55 AMmutex.withLock
will only run 1 at the same time yes, it’s governed by the instance of Mutex
, which suspend method etc you use does not matter.
you might want to check https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/get-and-update.html though, would not need a Mutex in that caseephemient
05/03/2023, 8:57 AMcache.update { it + brand.brandId }
cache.update { it - brand.brandId }
cache.value = buildSet { favorites.mapTo(this) { it.brandId } }
is sufficient to match behaviorjuliocbcotta
05/03/2023, 8:57 AMTijl
05/03/2023, 8:59 AMupdate
depending on your exact usecaseephemient
05/03/2023, 9:05 AMprivate val cache = mutableSetOf<String>()
private val _flow = MutableStateFlow(cache.toSet())
val flow: StateFlow<String>
get() = _flow.asStateFlow()
suspend fun add(brand: Favorite) {
mutex.withLock {
cache.add(brand.brandId)
_flow.value = cache.toSet()
}
}
etc. but for this use case that pattern is not necessaryjuliocbcotta
05/03/2023, 9:10 AM