diff --git a/kotlinx-coroutines-core/common/src/sync/Mutex.kt b/kotlinx-coroutines-core/common/src/sync/Mutex.kt index 769c9f1168..61e046c77a 100644 --- a/kotlinx-coroutines-core/common/src/sync/Mutex.kt +++ b/kotlinx-coroutines-core/common/src/sync/Mutex.kt @@ -9,6 +9,7 @@ import kotlinx.coroutines.* import kotlinx.coroutines.internal.* import kotlinx.coroutines.intrinsics.* import kotlinx.coroutines.selects.* +import kotlin.contracts.* import kotlin.coroutines.* import kotlin.jvm.* import kotlin.native.concurrent.* @@ -106,7 +107,12 @@ public fun Mutex(locked: Boolean = false): Mutex = * * @return the return value of the action. */ +@OptIn(ExperimentalContracts::class) public suspend inline fun Mutex.withLock(owner: Any? = null, action: () -> T): T { + contract { + callsInPlace(action, InvocationKind.EXACTLY_ONCE) + } + lock(owner) try { return action() diff --git a/kotlinx-coroutines-core/common/src/sync/Semaphore.kt b/kotlinx-coroutines-core/common/src/sync/Semaphore.kt index 125bbaaeb5..27c976ce3f 100644 --- a/kotlinx-coroutines-core/common/src/sync/Semaphore.kt +++ b/kotlinx-coroutines-core/common/src/sync/Semaphore.kt @@ -7,6 +7,7 @@ package kotlinx.coroutines.sync import kotlinx.atomicfu.* import kotlinx.coroutines.* import kotlinx.coroutines.internal.* +import kotlin.contracts.* import kotlin.coroutines.* import kotlin.math.* import kotlin.native.concurrent.SharedImmutable @@ -74,7 +75,12 @@ public fun Semaphore(permits: Int, acquiredPermits: Int = 0): Semaphore = Semaph * * @return the return value of the [action]. */ +@OptIn(ExperimentalContracts::class) public suspend inline fun Semaphore.withPermit(action: () -> T): T { + contract { + callsInPlace(action, InvocationKind.EXACTLY_ONCE) + } + acquire() try { return action()