From 72e880412a3807280c75ad98968c3bb415393397 Mon Sep 17 00:00:00 2001 From: Yang Date: Sun, 30 Apr 2023 13:43:02 +1000 Subject: [PATCH 1/4] Use `ConcurrentHashMap` for JVM target. --- cache4k/build.gradle.kts | 1 + .../cache4k/ConcurrentMutableMap.kt | 10 +++++++ .../cache4k/KeyedSynchronizer.kt | 5 ++-- .../reactivecircus/cache4k/RealCache.kt | 5 ++-- .../cache4k/ConcurrentMutableMap.kt | 29 +++++++++++++++++++ .../cache4k/ConcurrentMutableMap.kt | 29 +++++++++++++++++++ 6 files changed, 73 insertions(+), 6 deletions(-) create mode 100644 cache4k/src/commonMain/kotlin/io/github/reactivecircus/cache4k/ConcurrentMutableMap.kt create mode 100644 cache4k/src/jvmMain/kotlin/io/github/reactivecircus/cache4k/ConcurrentMutableMap.kt create mode 100644 cache4k/src/nonJvmMain/kotlin/io/github/reactivecircus/cache4k/ConcurrentMutableMap.kt diff --git a/cache4k/build.gradle.kts b/cache4k/build.gradle.kts index d50fd2d..4375875 100644 --- a/cache4k/build.gradle.kts +++ b/cache4k/build.gradle.kts @@ -24,6 +24,7 @@ kotlin { } jvmLincheck { dependencies { + dependsOn(jvmMain) implementation(kotlin("test-junit5")) implementation(libs.lincheck) } diff --git a/cache4k/src/commonMain/kotlin/io/github/reactivecircus/cache4k/ConcurrentMutableMap.kt b/cache4k/src/commonMain/kotlin/io/github/reactivecircus/cache4k/ConcurrentMutableMap.kt new file mode 100644 index 0000000..bd98ee0 --- /dev/null +++ b/cache4k/src/commonMain/kotlin/io/github/reactivecircus/cache4k/ConcurrentMutableMap.kt @@ -0,0 +1,10 @@ +package io.github.reactivecircus.cache4k + +internal expect class ConcurrentMutableMap() { + val size: Int + val values: Collection + operator fun get(key: Key): Value? + fun put(key: Key, value: Value): Value? + fun remove(key: Key): Value? + fun clear() +} diff --git a/cache4k/src/commonMain/kotlin/io/github/reactivecircus/cache4k/KeyedSynchronizer.kt b/cache4k/src/commonMain/kotlin/io/github/reactivecircus/cache4k/KeyedSynchronizer.kt index 3f7e1bc..d9f006f 100644 --- a/cache4k/src/commonMain/kotlin/io/github/reactivecircus/cache4k/KeyedSynchronizer.kt +++ b/cache4k/src/commonMain/kotlin/io/github/reactivecircus/cache4k/KeyedSynchronizer.kt @@ -1,6 +1,5 @@ package io.github.reactivecircus.cache4k -import co.touchlab.stately.collections.IsoMutableMap import kotlinx.atomicfu.locks.reentrantLock import kotlinx.atomicfu.locks.withLock import kotlinx.coroutines.sync.Mutex @@ -11,7 +10,7 @@ import kotlinx.coroutines.sync.withLock */ internal class KeyedSynchronizer { - private val keyBasedMutexes = IsoMutableMap() + private val keyBasedMutexes = ConcurrentMutableMap() private val mapLock = reentrantLock() @@ -40,7 +39,7 @@ internal class KeyedSynchronizer { mutexEntry.counter++ // save the lock entry to the map if it has just been created if (keyBasedMutexes[key] == null) { - keyBasedMutexes[key] = mutexEntry + keyBasedMutexes.put(key, mutexEntry) } return mutexEntry.mutex diff --git a/cache4k/src/commonMain/kotlin/io/github/reactivecircus/cache4k/RealCache.kt b/cache4k/src/commonMain/kotlin/io/github/reactivecircus/cache4k/RealCache.kt index 08e6b5b..48e2541 100644 --- a/cache4k/src/commonMain/kotlin/io/github/reactivecircus/cache4k/RealCache.kt +++ b/cache4k/src/commonMain/kotlin/io/github/reactivecircus/cache4k/RealCache.kt @@ -1,6 +1,5 @@ package io.github.reactivecircus.cache4k -import co.touchlab.stately.collections.IsoMutableMap import co.touchlab.stately.collections.IsoMutableSet import kotlinx.atomicfu.AtomicRef import kotlinx.atomicfu.atomic @@ -38,7 +37,7 @@ internal class RealCache( private val eventListener: CacheEventListener?, ) : Cache { - private val cacheEntries = IsoMutableMap>() + private val cacheEntries = ConcurrentMutableMap>() /** * Whether to perform size based evictions. @@ -138,7 +137,7 @@ internal class RealCache( writeTimeMark = atomic(nowTimeMark), ) recordWrite(newEntry) - cacheEntries[key] = newEntry + cacheEntries.put(key, newEntry) } onEvent( oldValue?.let { diff --git a/cache4k/src/jvmMain/kotlin/io/github/reactivecircus/cache4k/ConcurrentMutableMap.kt b/cache4k/src/jvmMain/kotlin/io/github/reactivecircus/cache4k/ConcurrentMutableMap.kt new file mode 100644 index 0000000..40ee1e5 --- /dev/null +++ b/cache4k/src/jvmMain/kotlin/io/github/reactivecircus/cache4k/ConcurrentMutableMap.kt @@ -0,0 +1,29 @@ +package io.github.reactivecircus.cache4k + +import java.util.concurrent.ConcurrentHashMap + +internal actual class ConcurrentMutableMap { + private val map = ConcurrentHashMap() + + actual val size: Int + get() = map.size + + actual val values: Collection + get() = map.values + + actual operator fun get(key: Key): Value? { + return map[key] + } + + actual fun put(key: Key, value: Value): Value? { + return map.put(key, value) + } + + actual fun remove(key: Key): Value? { + return map.remove(key) + } + + actual fun clear() { + map.clear() + } +} diff --git a/cache4k/src/nonJvmMain/kotlin/io/github/reactivecircus/cache4k/ConcurrentMutableMap.kt b/cache4k/src/nonJvmMain/kotlin/io/github/reactivecircus/cache4k/ConcurrentMutableMap.kt new file mode 100644 index 0000000..a43c0c2 --- /dev/null +++ b/cache4k/src/nonJvmMain/kotlin/io/github/reactivecircus/cache4k/ConcurrentMutableMap.kt @@ -0,0 +1,29 @@ +package io.github.reactivecircus.cache4k + +import co.touchlab.stately.collections.IsoMutableMap + +internal actual class ConcurrentMutableMap { + private val map = IsoMutableMap() + + actual val size: Int + get() = map.size + + actual val values: Collection + get() = map.values + + actual operator fun get(key: Key): Value? { + return map[key] + } + + actual fun put(key: Key, value: Value): Value? { + return map.put(key, value) + } + + actual fun remove(key: Key): Value? { + return map.remove(key) + } + + actual fun clear() { + map.clear() + } +} From d0f9f74d476f6dc216a21e99a7ee64963a6d2265 Mon Sep 17 00:00:00 2001 From: Yang Date: Sun, 30 Apr 2023 14:29:36 +1000 Subject: [PATCH 2/4] Simplify `actual` implementations. --- .../cache4k/ConcurrentMutableMap.kt | 22 +++++-------------- .../cache4k/ConcurrentMutableMap.kt | 22 +++++-------------- 2 files changed, 12 insertions(+), 32 deletions(-) diff --git a/cache4k/src/jvmMain/kotlin/io/github/reactivecircus/cache4k/ConcurrentMutableMap.kt b/cache4k/src/jvmMain/kotlin/io/github/reactivecircus/cache4k/ConcurrentMutableMap.kt index 40ee1e5..f63f129 100644 --- a/cache4k/src/jvmMain/kotlin/io/github/reactivecircus/cache4k/ConcurrentMutableMap.kt +++ b/cache4k/src/jvmMain/kotlin/io/github/reactivecircus/cache4k/ConcurrentMutableMap.kt @@ -5,25 +5,15 @@ import java.util.concurrent.ConcurrentHashMap internal actual class ConcurrentMutableMap { private val map = ConcurrentHashMap() - actual val size: Int - get() = map.size + actual val size: Int get() = map.size - actual val values: Collection - get() = map.values + actual val values: Collection get() = map.values - actual operator fun get(key: Key): Value? { - return map[key] - } + actual operator fun get(key: Key): Value? = map[key] - actual fun put(key: Key, value: Value): Value? { - return map.put(key, value) - } + actual fun put(key: Key, value: Value): Value? = map.put(key, value) - actual fun remove(key: Key): Value? { - return map.remove(key) - } + actual fun remove(key: Key): Value? = map.remove(key) - actual fun clear() { - map.clear() - } + actual fun clear() = map.clear() } diff --git a/cache4k/src/nonJvmMain/kotlin/io/github/reactivecircus/cache4k/ConcurrentMutableMap.kt b/cache4k/src/nonJvmMain/kotlin/io/github/reactivecircus/cache4k/ConcurrentMutableMap.kt index a43c0c2..ff14e29 100644 --- a/cache4k/src/nonJvmMain/kotlin/io/github/reactivecircus/cache4k/ConcurrentMutableMap.kt +++ b/cache4k/src/nonJvmMain/kotlin/io/github/reactivecircus/cache4k/ConcurrentMutableMap.kt @@ -5,25 +5,15 @@ import co.touchlab.stately.collections.IsoMutableMap internal actual class ConcurrentMutableMap { private val map = IsoMutableMap() - actual val size: Int - get() = map.size + actual val size: Int get() = map.size - actual val values: Collection - get() = map.values + actual val values: Collection get() = map.values - actual operator fun get(key: Key): Value? { - return map[key] - } + actual operator fun get(key: Key): Value? = map[key] - actual fun put(key: Key, value: Value): Value? { - return map.put(key, value) - } + actual fun put(key: Key, value: Value): Value? = map.put(key, value) - actual fun remove(key: Key): Value? { - return map.remove(key) - } + actual fun remove(key: Key): Value? = map.remove(key) - actual fun clear() { - map.clear() - } + actual fun clear() = map.clear() } From 76e44e25c84ce30af12ba5c72877a65ac1066c68 Mon Sep 17 00:00:00 2001 From: Yang Date: Fri, 23 Feb 2024 23:01:27 +1100 Subject: [PATCH 3/4] Fix `nonJvm` and `jvmLincheck` sourcesets. --- build-logic/gradle.properties | 1 - .../buildlogic/convention/ConventionPlugin.kt | 19 ++++++++----------- cache4k/build.gradle.kts | 1 - gradle.properties | 1 - 4 files changed, 8 insertions(+), 14 deletions(-) diff --git a/build-logic/gradle.properties b/build-logic/gradle.properties index 771574b..917f4a3 100644 --- a/build-logic/gradle.properties +++ b/build-logic/gradle.properties @@ -5,4 +5,3 @@ org.gradle.configuration-cache=true org.gradle.configuration-cache.problems=warn kotlin.code.style=official -kotlin.experimental.tryK2=true diff --git a/build-logic/src/main/kotlin/io/github/reactivecircus/cache4k/buildlogic/convention/ConventionPlugin.kt b/build-logic/src/main/kotlin/io/github/reactivecircus/cache4k/buildlogic/convention/ConventionPlugin.kt index b19ffcc..4237d54 100644 --- a/build-logic/src/main/kotlin/io/github/reactivecircus/cache4k/buildlogic/convention/ConventionPlugin.kt +++ b/build-logic/src/main/kotlin/io/github/reactivecircus/cache4k/buildlogic/convention/ConventionPlugin.kt @@ -183,22 +183,19 @@ private fun KotlinMultiplatformExtension.configureTargets(project: Project) { applyDefaultHierarchyTemplate() sourceSets { - val jvmAndIos by creating { + val nonJvmMain by creating { dependsOn(commonMain.get()) } - iosMain.get().dependsOn(jvmAndIos) - jvmMain.get().dependsOn(jvmAndIos) - - val nonJvm by creating { - dependsOn(commonMain.get()) + val jvmLincheck by getting { + dependsOn(jvmMain.get()) } - jsMain.get().dependsOn(nonJvm) + jsMain.get().dependsOn(nonJvmMain) @Suppress("UnusedPrivateProperty") val wasmJsMain by getting { - dependsOn(nonJvm) + dependsOn(nonJvmMain) } - appleMain.get().dependsOn(nonJvm) - linuxMain.get().dependsOn(nonJvm) - mingwMain.get().dependsOn(nonJvm) + appleMain.get().dependsOn(nonJvmMain) + linuxMain.get().dependsOn(nonJvmMain) + mingwMain.get().dependsOn(nonJvmMain) } } diff --git a/cache4k/build.gradle.kts b/cache4k/build.gradle.kts index 4375875..d50fd2d 100644 --- a/cache4k/build.gradle.kts +++ b/cache4k/build.gradle.kts @@ -24,7 +24,6 @@ kotlin { } jvmLincheck { dependencies { - dependsOn(jvmMain) implementation(kotlin("test-junit5")) implementation(libs.lincheck) } diff --git a/gradle.properties b/gradle.properties index 6b111db..9600e9e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -18,4 +18,3 @@ org.gradle.configureondemand=true org.gradle.caching=true kotlin.code.style=official -kotlin.experimental.tryK2=false From 8581b07f7374f90573730dbb6ee5a1a6f00a5d3c Mon Sep 17 00:00:00 2001 From: Yang Date: Fri, 23 Feb 2024 23:06:54 +1100 Subject: [PATCH 4/4] detekt --- .../cache4k/buildlogic/convention/ConventionPlugin.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build-logic/src/main/kotlin/io/github/reactivecircus/cache4k/buildlogic/convention/ConventionPlugin.kt b/build-logic/src/main/kotlin/io/github/reactivecircus/cache4k/buildlogic/convention/ConventionPlugin.kt index 4237d54..6f8f65d 100644 --- a/build-logic/src/main/kotlin/io/github/reactivecircus/cache4k/buildlogic/convention/ConventionPlugin.kt +++ b/build-logic/src/main/kotlin/io/github/reactivecircus/cache4k/buildlogic/convention/ConventionPlugin.kt @@ -182,6 +182,7 @@ private fun KotlinMultiplatformExtension.configureTargets(project: Project) { mingwX64() applyDefaultHierarchyTemplate() + @Suppress("UnusedPrivateProperty") sourceSets { val nonJvmMain by creating { dependsOn(commonMain.get()) @@ -190,7 +191,6 @@ private fun KotlinMultiplatformExtension.configureTargets(project: Project) { dependsOn(jvmMain.get()) } jsMain.get().dependsOn(nonJvmMain) - @Suppress("UnusedPrivateProperty") val wasmJsMain by getting { dependsOn(nonJvmMain) }