Introduce NamedMutex

Maybe we should have a better impl?
This commit is contained in:
tarsin committed 2023-04-03 22:55:24 +08:00
1 parent 18c205dde2
commit 3762b69fed
2 files changed
+33 -4

No files matched your search

@@ -34,10 +34,10 @@ import kotlinx.coroutines.currentCoroutineContext
import kotlinx.coroutines.ensureActive
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.Semaphore
import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.sync.withPermit
import moe.tarsin.coroutines.NamedMutex
import moe.tarsin.coroutines.withLock
import java.nio.ByteBuffer
class ArchivePageLoader(context: Context, private val uri: Uri, passwdFlow: Flow<String>) : PageLoader2(), CoroutineScope {
@@ -79,7 +79,7 @@ class ArchivePageLoader(context: Context, private val uri: Uri, passwdFlow: Flow
}
private val mJobMap = hashMapOf<Int, Job>()
private val mWorkerMutex by lazy { (0 until size).map { Mutex() } }
private val mWorkerMutex = NamedMutex<Int>()
private val mSemaphore = Semaphore(4)
override fun onRequest(index: Int) {
@@ -87,7 +87,7 @@ class ArchivePageLoader(context: Context, private val uri: Uri, passwdFlow: Flow
val current = mJobMap[index]
if (current?.isActive != true) {
mJobMap[index] = launch {
mWorkerMutex[index].withLock {
mWorkerMutex.withLock(index) {
mSemaphore.withPermit {
doRealWork(index)
}
@@ -0,0 +1,29 @@
package moe.tarsin.coroutines
import arrow.core.memoize
import kotlinx.coroutines.sync.Mutex
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract
class NamedMutex<T> {
val innerMutexGetter = { _: T -> Mutex() }.memoize()
}
suspend inline fun <T, K> NamedMutex<K>.withLock(key: K, owner: Any? = null, action: () -> T): T {
contract {
callsInPlace(action, InvocationKind.EXACTLY_ONCE)
}
val mutex = synchronized(innerMutexGetter) {
innerMutexGetter(key)
}
mutex.run {
lock(owner)
try {
return action()
} finally {
unlock(owner)
}
}
}