KMutexGuard

Ensures that only one coroutine at a time can execute a critical section.

Wraps Mutex with an observable isLocked state and optional "skip if busy" semantics via tryRun.

Serialize concurrent writes

val guard = MutexGuard()

// Multiple coroutines calling save() will queue up safely:
suspend fun save(data: Data) = guard.run {
repository.write(data)
}

Skip if already running (debounce-style)

val guard = MutexGuard()

// A second refresh call while the first is in progress does nothing:
suspend fun refresh() = guard.tryRun {
api.fetchLatest()
}

Observe lock state

guard.isLocked.collect { locked -> showSpinner(locked) }

Constructors

Link copied to clipboard
constructor()

Properties

Link copied to clipboard
val isLocked: StateFlow<Boolean>

true while a coroutine holds the lock.

Functions

Link copied to clipboard
suspend fun <T> run(block: suspend () -> T): T

Suspends until the lock is available, then executes block exclusively. Always runs block, even if other coroutines are queued behind it.

Link copied to clipboard
suspend fun <T> tryRun(block: suspend () -> T): T?

Executes block only if the lock is not currently held. If another coroutine is already inside run or tryRun, this call returns null immediately without suspending.