Quantum64
04/07/2022, 2:38 AMclass KeyedMutex<T> {
@PublishedApi
internal val mutexes = ConcurrentHashMap<T, Container>()
data class Container(
val mutex: Mutex,
val holders: Int
)
suspend inline fun <U> use(key: T, closure: () -> U): U {
val result = mutexes
.compute(key) { _, container ->
container?.copy(holders = container.holders + 1)
?: Container(Mutex(), holders = 1)
}!! // always associates the key
.mutex
.withLock(action = closure)
mutexes.computeIfPresent(key) { _, container ->
if (container.holders > 1) container.copy(holders = container.holders - 1)
else null
}
return result
}
}
ildar.i [Android]
04/07/2022, 3:54 AMQuantum64
04/07/2022, 5:02 AMephemient
04/07/2022, 10:43 AMclass KeyedMutex<in T>(concurrencyLevel: Int = 16) {
init {
require(concurrencyLevel > 0)
}
private val mutexes = Array(concurrencyLevel) { Mutex() }
@PublishedApi
internal fun get(key: T): Mutex = mutexes[key.hashCode().mod(mutexes.size)]
}
suspend fun <T, R> KeyedMutex<T>.use(key: T, owner: Any? = null, block: suspend () -> R): R =
get(key).withLock(owner) { block() }
Quantum64
04/08/2022, 1:40 AMephemient
04/09/2022, 12:40 AM