Michael Strasser
05/04/2023, 7:11 AMMutableStateFlow.
Because the value property is thread-safe, does it make sense to use MutableStateFlow as a multiplatform, thread-safe delegate, like this?
class ThreadSafeMap<K, V>(
vararg pairs: Pair<K, V>
) : MutableMap<K, V> by MutableStateFlow(
mutableMapOf(*pairs)
).valueNicklas Jensen
05/04/2023, 7:47 AMMutableMap thread-safe since you're effectively exposing it to the caller as-is (through delegation). To make it thread-safe you'd have to implement the MutableMap interface yourself while making sure every operation you perform is thread-safe.Michael Strasser
05/04/2023, 9:52 AMMutableStateFlow object when using delegation. (The delegate is the MutableMap it contains.)
Is there a way to get access to the delegate object within the delegating class?Michael Strasser
05/04/2023, 10:04 AMMutableMap implementation without delegation:
class ThreadSafeMap<K, V>(
vararg pairs: Pair<K, V>
): MutableMap<K, V> {
private val _mapFlow = MutableStateFlow(mutableMapOf(*pairs))
// Read-only property
override val keys: MutableSet<K>
get() = _mapFlow.value.entries
// Function without a return value
override fun clear(): Unit = _mapFlow.update { it.apply { clear() } }
// Function that returns a value
override fun remove(key: K): V? {
var previousValue: V? = null
// The lambda provided to MutableStateFlow.update()
// needs to return the mutable map
_mapFlow.update { it.apply { previousValue = remove(key) } }
return previousValue
}
// etc.
}
I think this would work.Nicklas Jensen
05/04/2023, 10:57 AMupdate function of MutableStateFlow is atomic, but in reality, as long as you're storing and mutating a MutableMap in your MutableStateFlow you will find it hard to make it "thread-safe". A "simple" version of a thread-safe MutableMap could be implemented using locks from atomic-fu, or by storing an immutable Map in your MutableStateFlow and just updating that in your update function. Doing so you may as well use atomic<T> from atomic-fu, e.g. like in this snippet.Nicklas Jensen
05/04/2023, 10:58 AMMap though? If you're only modifying it from a single thread, then you can just use an immutable Map stored in an AtomicRef and read it from as many threads as you like. You only need the "mutation thread safety" if you're actually mutating the Map from several threadsMichael Strasser
05/04/2023, 11:06 AMConcurrentHashMap.
But I want to make Klogging multiplatform so I need a different solution. I had looked a bit at atomic-fu but wasn’t sure if was still experimental.Nicklas Jensen
05/04/2023, 11:11 AMMutableStateFlow 😄Nicklas Jensen
05/04/2023, 11:12 AMfun get(key: K): V? = map.value.get(key)
Because the underlying Map is immutable (I have updated my snippet)