From aa62d56456df8de199e57c21442bbe91ffb12c0c Mon Sep 17 00:00:00 2001 From: zhouxin Date: Mon, 11 May 2020 18:22:55 +0800 Subject: [PATCH 1/4] refactor(Mutex): added EXACTLY_ONCE contract --- kotlinx-coroutines-core/common/src/sync/Mutex.kt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/kotlinx-coroutines-core/common/src/sync/Mutex.kt b/kotlinx-coroutines-core/common/src/sync/Mutex.kt index 769c9f1168..763b8cb6d3 100644 --- a/kotlinx-coroutines-core/common/src/sync/Mutex.kt +++ b/kotlinx-coroutines-core/common/src/sync/Mutex.kt @@ -107,6 +107,10 @@ public fun Mutex(locked: Boolean = false): Mutex = * @return the return value of the action. */ public suspend inline fun Mutex.withLock(owner: Any? = null, action: () -> T): T { + contract { + callsInPlace(action, InvocationKind.EXACTLY_ONCE) + } + lock(owner) try { return action() From 6a99b41767319e334d726e948cc1d5ab3dc09d70 Mon Sep 17 00:00:00 2001 From: zhouxin Date: Tue, 12 May 2020 17:44:23 +0800 Subject: [PATCH 2/4] refactor(Semaphore.kt): withPermit() added EXACTLY_ONCE contract --- kotlinx-coroutines-core/common/src/sync/Mutex.kt | 4 ++++ kotlinx-coroutines-core/common/src/sync/Semaphore.kt | 8 ++++++++ kotlinx-coroutines-core/common/test/sync/MutexTest.kt | 2 ++ kotlinx-coroutines-core/common/test/sync/SemaphoreTest.kt | 2 ++ kotlinx-coroutines-core/jvm/test/guide/example-sync-06.kt | 2 ++ 5 files changed, 18 insertions(+) diff --git a/kotlinx-coroutines-core/common/src/sync/Mutex.kt b/kotlinx-coroutines-core/common/src/sync/Mutex.kt index 763b8cb6d3..7db51f1d23 100644 --- a/kotlinx-coroutines-core/common/src/sync/Mutex.kt +++ b/kotlinx-coroutines-core/common/src/sync/Mutex.kt @@ -9,6 +9,9 @@ import kotlinx.coroutines.* import kotlinx.coroutines.internal.* import kotlinx.coroutines.intrinsics.* import kotlinx.coroutines.selects.* +import kotlin.contracts.ExperimentalContracts +import kotlin.contracts.InvocationKind +import kotlin.contracts.contract import kotlin.coroutines.* import kotlin.jvm.* import kotlin.native.concurrent.* @@ -106,6 +109,7 @@ public fun Mutex(locked: Boolean = false): Mutex = * * @return the return value of the action. */ +@ExperimentalContracts public suspend inline fun Mutex.withLock(owner: Any? = null, action: () -> T): T { contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) diff --git a/kotlinx-coroutines-core/common/src/sync/Semaphore.kt b/kotlinx-coroutines-core/common/src/sync/Semaphore.kt index 125bbaaeb5..310db25f9d 100644 --- a/kotlinx-coroutines-core/common/src/sync/Semaphore.kt +++ b/kotlinx-coroutines-core/common/src/sync/Semaphore.kt @@ -7,6 +7,9 @@ package kotlinx.coroutines.sync import kotlinx.atomicfu.* import kotlinx.coroutines.* import kotlinx.coroutines.internal.* +import kotlin.contracts.ExperimentalContracts +import kotlin.contracts.InvocationKind +import kotlin.contracts.contract import kotlin.coroutines.* import kotlin.math.* import kotlin.native.concurrent.SharedImmutable @@ -74,7 +77,12 @@ public fun Semaphore(permits: Int, acquiredPermits: Int = 0): Semaphore = Semaph * * @return the return value of the [action]. */ +@ExperimentalContracts public suspend inline fun Semaphore.withPermit(action: () -> T): T { + contract { + callsInPlace(action, InvocationKind.EXACTLY_ONCE) + } + acquire() try { return action() diff --git a/kotlinx-coroutines-core/common/test/sync/MutexTest.kt b/kotlinx-coroutines-core/common/test/sync/MutexTest.kt index c5d0ccf187..bf27bc3708 100644 --- a/kotlinx-coroutines-core/common/test/sync/MutexTest.kt +++ b/kotlinx-coroutines-core/common/test/sync/MutexTest.kt @@ -5,8 +5,10 @@ package kotlinx.coroutines.sync import kotlinx.coroutines.* +import kotlin.contracts.ExperimentalContracts import kotlin.test.* +@ExperimentalContracts class MutexTest : TestBase() { @Test fun testSimple() = runTest { diff --git a/kotlinx-coroutines-core/common/test/sync/SemaphoreTest.kt b/kotlinx-coroutines-core/common/test/sync/SemaphoreTest.kt index b4ff88b895..a72bf6ca1e 100644 --- a/kotlinx-coroutines-core/common/test/sync/SemaphoreTest.kt +++ b/kotlinx-coroutines-core/common/test/sync/SemaphoreTest.kt @@ -1,6 +1,7 @@ package kotlinx.coroutines.sync import kotlinx.coroutines.* +import kotlin.contracts.ExperimentalContracts import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertFalse @@ -59,6 +60,7 @@ class SemaphoreTest : TestBase() { assertEquals(0, semaphore.availablePermits) } + @ExperimentalContracts @Test fun withSemaphoreTest() = runTest { val semaphore = Semaphore(1) diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-sync-06.kt b/kotlinx-coroutines-core/jvm/test/guide/example-sync-06.kt index e6c5f1bad3..c7798497bc 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-sync-06.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-sync-06.kt @@ -7,6 +7,7 @@ package kotlinx.coroutines.guide.exampleSync06 import kotlinx.coroutines.* import kotlinx.coroutines.sync.* +import kotlin.contracts.ExperimentalContracts import kotlin.system.* suspend fun massiveRun(action: suspend () -> Unit) { @@ -27,6 +28,7 @@ suspend fun massiveRun(action: suspend () -> Unit) { val mutex = Mutex() var counter = 0 +@ExperimentalContracts fun main() = runBlocking { withContext(Dispatchers.Default) { massiveRun { From a132210713c9278af60f38d5e80d1b5cf4e6c063 Mon Sep 17 00:00:00 2001 From: zhouxin Date: Wed, 13 May 2020 17:30:11 +0800 Subject: [PATCH 3/4] style: imports kotlin.contracts.* --- kotlinx-coroutines-core/common/src/sync/Mutex.kt | 4 +--- kotlinx-coroutines-core/common/src/sync/Semaphore.kt | 4 +--- kotlinx-coroutines-core/common/test/sync/MutexTest.kt | 2 +- kotlinx-coroutines-core/common/test/sync/SemaphoreTest.kt | 2 +- kotlinx-coroutines-core/jvm/test/guide/example-sync-06.kt | 2 +- 5 files changed, 5 insertions(+), 9 deletions(-) diff --git a/kotlinx-coroutines-core/common/src/sync/Mutex.kt b/kotlinx-coroutines-core/common/src/sync/Mutex.kt index 7db51f1d23..b9beec3dbd 100644 --- a/kotlinx-coroutines-core/common/src/sync/Mutex.kt +++ b/kotlinx-coroutines-core/common/src/sync/Mutex.kt @@ -9,9 +9,7 @@ import kotlinx.coroutines.* import kotlinx.coroutines.internal.* import kotlinx.coroutines.intrinsics.* import kotlinx.coroutines.selects.* -import kotlin.contracts.ExperimentalContracts -import kotlin.contracts.InvocationKind -import kotlin.contracts.contract +import kotlin.contracts.* import kotlin.coroutines.* import kotlin.jvm.* import kotlin.native.concurrent.* diff --git a/kotlinx-coroutines-core/common/src/sync/Semaphore.kt b/kotlinx-coroutines-core/common/src/sync/Semaphore.kt index 310db25f9d..33365821bd 100644 --- a/kotlinx-coroutines-core/common/src/sync/Semaphore.kt +++ b/kotlinx-coroutines-core/common/src/sync/Semaphore.kt @@ -7,9 +7,7 @@ package kotlinx.coroutines.sync import kotlinx.atomicfu.* import kotlinx.coroutines.* import kotlinx.coroutines.internal.* -import kotlin.contracts.ExperimentalContracts -import kotlin.contracts.InvocationKind -import kotlin.contracts.contract +import kotlin.contracts.* import kotlin.coroutines.* import kotlin.math.* import kotlin.native.concurrent.SharedImmutable diff --git a/kotlinx-coroutines-core/common/test/sync/MutexTest.kt b/kotlinx-coroutines-core/common/test/sync/MutexTest.kt index bf27bc3708..36805d72cf 100644 --- a/kotlinx-coroutines-core/common/test/sync/MutexTest.kt +++ b/kotlinx-coroutines-core/common/test/sync/MutexTest.kt @@ -5,7 +5,7 @@ package kotlinx.coroutines.sync import kotlinx.coroutines.* -import kotlin.contracts.ExperimentalContracts +import kotlin.contracts.* import kotlin.test.* @ExperimentalContracts diff --git a/kotlinx-coroutines-core/common/test/sync/SemaphoreTest.kt b/kotlinx-coroutines-core/common/test/sync/SemaphoreTest.kt index a72bf6ca1e..ae1cbde28d 100644 --- a/kotlinx-coroutines-core/common/test/sync/SemaphoreTest.kt +++ b/kotlinx-coroutines-core/common/test/sync/SemaphoreTest.kt @@ -1,7 +1,7 @@ package kotlinx.coroutines.sync import kotlinx.coroutines.* -import kotlin.contracts.ExperimentalContracts +import kotlin.contracts.* import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertFalse diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-sync-06.kt b/kotlinx-coroutines-core/jvm/test/guide/example-sync-06.kt index c7798497bc..e187877d94 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-sync-06.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-sync-06.kt @@ -7,7 +7,7 @@ package kotlinx.coroutines.guide.exampleSync06 import kotlinx.coroutines.* import kotlinx.coroutines.sync.* -import kotlin.contracts.ExperimentalContracts +import kotlin.contracts.* import kotlin.system.* suspend fun massiveRun(action: suspend () -> Unit) { From 752e0604d882eec219831dfe91c3cf2db0b3535b Mon Sep 17 00:00:00 2001 From: zhouxin Date: Wed, 13 May 2020 20:15:22 +0800 Subject: [PATCH 4/4] refacotr: Mutex.withLock()/Semaphore.withPermit() change @ExperimentalContracts to @OptIn(ExperimentalContracts::class) --- kotlinx-coroutines-core/common/src/sync/Mutex.kt | 2 +- kotlinx-coroutines-core/common/src/sync/Semaphore.kt | 2 +- kotlinx-coroutines-core/common/test/sync/MutexTest.kt | 2 -- kotlinx-coroutines-core/common/test/sync/SemaphoreTest.kt | 2 -- kotlinx-coroutines-core/jvm/test/guide/example-sync-06.kt | 2 -- 5 files changed, 2 insertions(+), 8 deletions(-) diff --git a/kotlinx-coroutines-core/common/src/sync/Mutex.kt b/kotlinx-coroutines-core/common/src/sync/Mutex.kt index b9beec3dbd..61e046c77a 100644 --- a/kotlinx-coroutines-core/common/src/sync/Mutex.kt +++ b/kotlinx-coroutines-core/common/src/sync/Mutex.kt @@ -107,7 +107,7 @@ public fun Mutex(locked: Boolean = false): Mutex = * * @return the return value of the action. */ -@ExperimentalContracts +@OptIn(ExperimentalContracts::class) public suspend inline fun Mutex.withLock(owner: Any? = null, action: () -> T): T { contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) diff --git a/kotlinx-coroutines-core/common/src/sync/Semaphore.kt b/kotlinx-coroutines-core/common/src/sync/Semaphore.kt index 33365821bd..27c976ce3f 100644 --- a/kotlinx-coroutines-core/common/src/sync/Semaphore.kt +++ b/kotlinx-coroutines-core/common/src/sync/Semaphore.kt @@ -75,7 +75,7 @@ public fun Semaphore(permits: Int, acquiredPermits: Int = 0): Semaphore = Semaph * * @return the return value of the [action]. */ -@ExperimentalContracts +@OptIn(ExperimentalContracts::class) public suspend inline fun Semaphore.withPermit(action: () -> T): T { contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) diff --git a/kotlinx-coroutines-core/common/test/sync/MutexTest.kt b/kotlinx-coroutines-core/common/test/sync/MutexTest.kt index 36805d72cf..c5d0ccf187 100644 --- a/kotlinx-coroutines-core/common/test/sync/MutexTest.kt +++ b/kotlinx-coroutines-core/common/test/sync/MutexTest.kt @@ -5,10 +5,8 @@ package kotlinx.coroutines.sync import kotlinx.coroutines.* -import kotlin.contracts.* import kotlin.test.* -@ExperimentalContracts class MutexTest : TestBase() { @Test fun testSimple() = runTest { diff --git a/kotlinx-coroutines-core/common/test/sync/SemaphoreTest.kt b/kotlinx-coroutines-core/common/test/sync/SemaphoreTest.kt index ae1cbde28d..b4ff88b895 100644 --- a/kotlinx-coroutines-core/common/test/sync/SemaphoreTest.kt +++ b/kotlinx-coroutines-core/common/test/sync/SemaphoreTest.kt @@ -1,7 +1,6 @@ package kotlinx.coroutines.sync import kotlinx.coroutines.* -import kotlin.contracts.* import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertFalse @@ -60,7 +59,6 @@ class SemaphoreTest : TestBase() { assertEquals(0, semaphore.availablePermits) } - @ExperimentalContracts @Test fun withSemaphoreTest() = runTest { val semaphore = Semaphore(1) diff --git a/kotlinx-coroutines-core/jvm/test/guide/example-sync-06.kt b/kotlinx-coroutines-core/jvm/test/guide/example-sync-06.kt index e187877d94..e6c5f1bad3 100644 --- a/kotlinx-coroutines-core/jvm/test/guide/example-sync-06.kt +++ b/kotlinx-coroutines-core/jvm/test/guide/example-sync-06.kt @@ -7,7 +7,6 @@ package kotlinx.coroutines.guide.exampleSync06 import kotlinx.coroutines.* import kotlinx.coroutines.sync.* -import kotlin.contracts.* import kotlin.system.* suspend fun massiveRun(action: suspend () -> Unit) { @@ -28,7 +27,6 @@ suspend fun massiveRun(action: suspend () -> Unit) { val mutex = Mutex() var counter = 0 -@ExperimentalContracts fun main() = runBlocking { withContext(Dispatchers.Default) { massiveRun {