From 9d9530c4dee19326a29c29b26c71f5a4e8d44a2b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 14 Apr 2024 14:37:21 +0200 Subject: [PATCH 1/3] chore(deps): update peaceiris/actions-gh-pages action to v4 (#3401) * chore(deps): update peaceiris/actions-gh-pages action to v4 | datasource | package | from | to | | ----------- | -------------------------- | ---- | -- | | github-tags | peaceiris/actions-gh-pages | v3 | v4 | * Auto-update API files --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: renovate[bot] --- .github/workflows/githubpages.yaml | 2 +- arrow-libs/core/arrow-core/api/arrow-core.api | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/githubpages.yaml b/.github/workflows/githubpages.yaml index 1ef65d07097..668b15c8348 100644 --- a/.github/workflows/githubpages.yaml +++ b/.github/workflows/githubpages.yaml @@ -32,7 +32,7 @@ jobs: run: ./gradlew -Pversion=${{ github.event.release.tag_name }} dokkaHtmlMultiModule -Pgithubpages=true - name: Deploy to gh-pages - uses: peaceiris/actions-gh-pages@v3 + uses: peaceiris/actions-gh-pages@v4 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: ./docs diff --git a/arrow-libs/core/arrow-core/api/arrow-core.api b/arrow-libs/core/arrow-core/api/arrow-core.api index dac3c700a4e..cb2dc667993 100644 --- a/arrow-libs/core/arrow-core/api/arrow-core.api +++ b/arrow-libs/core/arrow-core/api/arrow-core.api @@ -3593,7 +3593,6 @@ public abstract interface annotation class arrow/core/raise/RaiseDSL : java/lang public final class arrow/core/raise/RaiseKt { public static final fun _fold (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public static final fun _foldOrThrow (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public static final fun _foldUnsafe (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public static final fun _merge (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public static final fun catch (Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public static final fun catch (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Lkotlin/jvm/functions/Function1; From ee641f858fbbcef27526db51dc0e7ba1ccc233cf Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 14 Apr 2024 14:38:40 +0200 Subject: [PATCH 2/3] chore(deps): update all dependencies (#3396) * chore(deps): update all dependencies | datasource | package | from | to | | ---------- | ----------------------------------------------------- | ----- | ------ | | maven | com.android.library:com.android.library.gradle.plugin | 8.3.0 | 8.3.1 | | maven | com.squareup.retrofit2:retrofit | 2.9.0 | 2.10.0 | | maven | com.squareup.retrofit2:converter-moshi | 2.9.0 | 2.10.0 | | maven | com.squareup.retrofit2:converter-gson | 2.9.0 | 2.10.0 | * Auto-update API files --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: renovate[bot] --- gradle/libs.versions.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 871ef576cd8..a3581a6167e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -19,12 +19,12 @@ knit = "0.5.0" kspVersion = "1.9.23-1.0.19" kotlinxSerialization = "1.6.3" mockWebServer = "4.12.0" -retrofit = "2.9.0" +retrofit = "2.10.0" retrofitKotlinxSerialization = "1.0.0" spotlessVersion = "6.25.0" compose = "1.6.3" composePlugin = "1.6.1" -agp = "8.3.0" +agp = "8.3.1" android-compileSdk = "34" cache4k = "0.13.0" From af99eb434ef6f405e4e44d13cfe142c143874711 Mon Sep 17 00:00:00 2001 From: Alejandro Serrano Date: Tue, 16 Apr 2024 08:52:23 +0200 Subject: [PATCH 3/3] Improvements to STM + do not expose internal members (#3398) * Improvements to STM + do not expose internal members * Additional fixes --- .../fx/arrow-fx-stm/api/arrow-fx-stm.api | 58 ------------ .../src/commonMain/kotlin/arrow/fx/stm/STM.kt | 18 ++-- .../kotlin/arrow/fx/stm/internal/Hamt.kt | 90 +++++++++---------- .../kotlin/arrow/fx/stm/internal/Impl.kt | 25 +++--- .../arrow/fx/stm/internal/RetryException.kt | 1 + 5 files changed, 66 insertions(+), 126 deletions(-) diff --git a/arrow-libs/fx/arrow-fx-stm/api/arrow-fx-stm.api b/arrow-libs/fx/arrow-fx-stm/api/arrow-fx-stm.api index 7a885252054..3e6770ca1b5 100644 --- a/arrow-libs/fx/arrow-fx-stm/api/arrow-fx-stm.api +++ b/arrow-libs/fx/arrow-fx-stm/api/arrow-fx-stm.api @@ -239,64 +239,6 @@ public final class arrow/fx/stm/internal/BlockedIndefinitely : java/lang/Throwab public fun ()V } -public abstract class arrow/fx/stm/internal/Branch { -} - -public final class arrow/fx/stm/internal/Branch$Branches : arrow/fx/stm/internal/Branch { - public fun (Larrow/fx/stm/internal/Hamt;)V - public final fun component1 ()Larrow/fx/stm/internal/Hamt; - public final fun copy (Larrow/fx/stm/internal/Hamt;)Larrow/fx/stm/internal/Branch$Branches; - public static synthetic fun copy$default (Larrow/fx/stm/internal/Branch$Branches;Larrow/fx/stm/internal/Hamt;ILjava/lang/Object;)Larrow/fx/stm/internal/Branch$Branches; - public fun equals (Ljava/lang/Object;)Z - public final fun getSub ()Larrow/fx/stm/internal/Hamt; - public fun hashCode ()I - public fun toString ()Ljava/lang/String; -} - -public final class arrow/fx/stm/internal/Branch$Leaf : arrow/fx/stm/internal/Branch { - public fun (I[Ljava/lang/Object;)V - public final fun component1 ()I - public final fun component2 ()[Ljava/lang/Object; - public final fun copy (I[Ljava/lang/Object;)Larrow/fx/stm/internal/Branch$Leaf; - public static synthetic fun copy$default (Larrow/fx/stm/internal/Branch$Leaf;I[Ljava/lang/Object;ILjava/lang/Object;)Larrow/fx/stm/internal/Branch$Leaf; - public fun equals (Ljava/lang/Object;)Z - public final fun getHash ()I - public final fun getValue ()[Ljava/lang/Object; - public fun hashCode ()I - public fun toString ()Ljava/lang/String; -} - -public final class arrow/fx/stm/internal/Hamt { - public static final field Companion Larrow/fx/stm/internal/Hamt$Companion; - public fun (Larrow/fx/stm/TVar;)V - public final fun component1 ()Larrow/fx/stm/TVar; - public final fun copy (Larrow/fx/stm/TVar;)Larrow/fx/stm/internal/Hamt; - public static synthetic fun copy$default (Larrow/fx/stm/internal/Hamt;Larrow/fx/stm/TVar;ILjava/lang/Object;)Larrow/fx/stm/internal/Hamt; - public fun equals (Ljava/lang/Object;)Z - public final fun getBranches ()Larrow/fx/stm/TVar; - public fun hashCode ()I - public fun toString ()Ljava/lang/String; -} - -public final class arrow/fx/stm/internal/Hamt$Companion { - public final fun new (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; -} - -public final class arrow/fx/stm/internal/HamtKt { - public static final field ARR_SIZE I - public static final field DEPTH_STEP I - public static final field MASK I - public static final fun alterHamtWithHash (Larrow/fx/stm/STM;Larrow/fx/stm/internal/Hamt;ILkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Z - public static final fun atDepth (II)I - public static final fun clearHamt (Larrow/fx/stm/STM;Larrow/fx/stm/internal/Hamt;)V - public static final fun index (I)I - public static final fun indexAtDepth (II)I - public static final fun lookupHamtWithHash (Larrow/fx/stm/STM;Larrow/fx/stm/internal/Hamt;ILkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public static final fun newHamt (Larrow/fx/stm/STM;)Larrow/fx/stm/internal/Hamt; - public static final fun nextDepth (I)I - public static final fun pair (Larrow/fx/stm/STM;IILarrow/fx/stm/internal/Branch;ILarrow/fx/stm/internal/Branch;)Larrow/fx/stm/internal/Hamt; -} - public final class arrow/fx/stm/internal/RetryException : java/lang/Throwable { public static final field INSTANCE Larrow/fx/stm/internal/RetryException; public fun fillInStackTrace ()Ljava/lang/Throwable; diff --git a/arrow-libs/fx/arrow-fx-stm/src/commonMain/kotlin/arrow/fx/stm/STM.kt b/arrow-libs/fx/arrow-fx-stm/src/commonMain/kotlin/arrow/fx/stm/STM.kt index 895be245622..9854ff8f9d1 100644 --- a/arrow-libs/fx/arrow-fx-stm/src/commonMain/kotlin/arrow/fx/stm/STM.kt +++ b/arrow-libs/fx/arrow-fx-stm/src/commonMain/kotlin/arrow/fx/stm/STM.kt @@ -310,7 +310,7 @@ public interface STM { * - When committing the value inside the [TVar], at the time of calling [write], has to be the * same as the current value otherwise the transaction will retry */ - public fun TVar.write(a: A): Unit + public fun TVar.write(a: A) /** * Modify the value of a [TVar] @@ -683,7 +683,7 @@ public interface STM { * * @see TSemaphore.tryAcquire for a version that does not retry. */ - public fun TSemaphore.acquire(n: Int): Unit { + public fun TSemaphore.acquire(n: Int) { val curr = v.read() check(curr - n >= 0) v.write(curr - n) @@ -1103,7 +1103,7 @@ public interface STM { * * > This function has to access both [TVar]'s and thus may lead to increased contention, use sparingly. */ - public fun TQueue.removeAll(pred: (A) -> Boolean): Unit { + public fun TQueue.removeAll(pred: (A) -> Boolean) { reads.modify { it.filter(pred) } writes.modify { it.filter(pred) } } @@ -1332,7 +1332,7 @@ public interface STM { * ``` * */ - public fun TMap.insert(k: K, v: V): Unit { + public fun TMap.insert(k: K, v: V) { alterHamtWithHash(hamt, hashFn(k), { it.first == k }) { k to v } } @@ -1397,8 +1397,8 @@ public interface STM { * ``` * */ - public fun TMap.update(k: K, fn: (V) -> V): Unit { - alterHamtWithHash(hamt, hashFn(k), { it.first == k }) { it?.second?.let(fn)?.let { k to it } } + public fun TMap.update(k: K, fn: (V) -> V) { + alterHamtWithHash(hamt, hashFn(k), { it.first == k }) { it?.second?.let(fn)?.let { r -> k to r } } } /** @@ -1420,7 +1420,7 @@ public interface STM { * ``` * */ - public fun TMap.remove(k: K): Unit { + public fun TMap.remove(k: K) { alterHamtWithHash(hamt, hashFn(k), { it.first == k }) { null } } @@ -1466,7 +1466,7 @@ public interface STM { * ``` * */ - public fun TSet.insert(a: A): Unit { + public fun TSet.insert(a: A) { alterHamtWithHash(hamt, hashFn(a), { it == a }) { a } } @@ -1509,7 +1509,7 @@ public interface STM { * ``` * */ - public fun TSet.remove(a: A): Unit { + public fun TSet.remove(a: A) { alterHamtWithHash(hamt, hashFn(a), { it == a }) { null } } } diff --git a/arrow-libs/fx/arrow-fx-stm/src/commonMain/kotlin/arrow/fx/stm/internal/Hamt.kt b/arrow-libs/fx/arrow-fx-stm/src/commonMain/kotlin/arrow/fx/stm/internal/Hamt.kt index 7ee918fdc38..d18312eaf09 100644 --- a/arrow-libs/fx/arrow-fx-stm/src/commonMain/kotlin/arrow/fx/stm/internal/Hamt.kt +++ b/arrow-libs/fx/arrow-fx-stm/src/commonMain/kotlin/arrow/fx/stm/internal/Hamt.kt @@ -8,13 +8,13 @@ import arrow.fx.stm.STM * * Based on http://lampwww.epfl.ch/papers/idealhashtrees.pdf and https://hackage.haskell.org/package/stm-hamt. */ -public data class Hamt(val branches: TVar?>>) { - public companion object { - public suspend fun new(): Hamt = Hamt(TVar.new(arrayOfNulls(ARR_SIZE))) +internal data class Hamt(val branches: TVar?>>) { + companion object { + suspend fun new(): Hamt = Hamt(TVar.new(arrayOfNulls(ARR_SIZE))) } } -public inline fun STM.lookupHamtWithHash(hmt: Hamt, hash: Int, test: (A) -> Boolean): A? { +internal fun STM.lookupHamtWithHash(hmt: Hamt, hash: Int, test: (A) -> Boolean): A? { var depth = 0 var hamt = hmt while (true) { @@ -22,7 +22,7 @@ public inline fun STM.lookupHamtWithHash(hmt: Hamt, hash: Int, test: (A) val branches = hamt.branches.read() when (val branch = branches[branchInd]) { null -> return null - is Branch.Leaf -> return@lookupHamtWithHash (branch.value as Array).find(test) + is Branch.Leaf -> return branch.value.find(test) is Branch.Branches -> { depth = depth.nextDepth() hamt = branch.sub @@ -31,7 +31,7 @@ public inline fun STM.lookupHamtWithHash(hmt: Hamt, hash: Int, test: (A) } } -public fun STM.pair(depth: Int, hash1: Int, branch1: Branch, hash2: Int, branch2: Branch): Hamt { +internal fun STM.pair(depth: Int, hash1: Int, branch1: Branch, hash2: Int, branch2: Branch): Hamt { val branchInd1 = hash1.indexAtDepth(depth) val branchInd2 = hash2.indexAtDepth(depth) val branches = arrayOfNulls>(ARR_SIZE) @@ -45,9 +45,9 @@ public fun STM.pair(depth: Int, hash1: Int, branch1: Branch, hash2: Int, return Hamt(newTVar(branches)) } -public fun STM.clearHamt(hamt: Hamt): Unit = hamt.branches.write(arrayOfNulls(ARR_SIZE)) +// internal fun STM.clearHamt(hamt: Hamt): Unit = hamt.branches.write(arrayOfNulls(ARR_SIZE)) -public inline fun STM.alterHamtWithHash( +internal fun STM.alterHamtWithHash( hamt: Hamt, hash: Int, test: (A) -> Boolean, @@ -62,46 +62,35 @@ public inline fun STM.alterHamtWithHash( null -> { val el = fn(null) ?: return false val new = branches.copyOf() - new[branchInd] = Branch.Leaf(hash, arrayOf(el)) + new[branchInd] = Branch.leaf(hash, el) hmt.branches.write(new) return true } is Branch.Leaf -> { - if (hash == branch.hash) { - val ind = (branch.value as Array).indexOfFirst(test).takeIf { it != -1 } + val atIndex = if (hash == branch.hash) { + val ind = branch.value.indexOfFirst(test).takeIf { it != -1 } when (val el = ind?.let { branch.value[it] }) { null -> { // insert new value with a colliding hash val newEl = fn(null) ?: return false - val new = branches.copyOf() - new[branchInd] = Branch.Leaf(hash, arrayOf(newEl, *branch.value)) - hmt.branches.write(new) - return true + Branch.leaf(hash, newEl, *branch.value) } else -> { - when (val newEl = fn(el)) { - null -> { + val newEl = fn(el) + when { + newEl == null && branch.value.size <= 1 -> + null + newEl == null -> { // remove element - if (branch.value.size > 1) { - val newLeafArray: Array = Array(branch.value.size - 1) { i -> - if (i >= ind) branch.value[i + 1] - else branch.value[i] - } - } else { - val new = branches.copyOf() - new[branchInd] = null - hmt.branches.write(new) - } - return true + val newLeafArray = branch.value.copyOf(branch.value.size - 1) as Array + branch.value.copyInto(newLeafArray, ind, ind + 1) + Branch.Leaf(hash, newLeafArray) } else -> { // update element val newLeafArr = branch.value.copyOf() newLeafArr[ind] = newEl - val new = branches.copyOf() - new[branchInd] = Branch.Leaf(hash, newLeafArr as Array) - hmt.branches.write(new) - return true + Branch.Leaf(hash, newLeafArr) } } } @@ -111,15 +100,16 @@ public inline fun STM.alterHamtWithHash( val newHamt = pair( depth.nextDepth(), hash, - Branch.Leaf(hash, arrayOf(el)), + Branch.leaf(hash, el), branch.hash, branch ) - val new = branches.copyOf() - new[branchInd] = Branch.Branches(newHamt) - hmt.branches.write(new) - return true + Branch.Branches(newHamt) } + val new = branches.copyOf() + new[branchInd] = atIndex + hmt.branches.write(new) + return true } is Branch.Branches -> { depth = depth.nextDepth() @@ -129,18 +119,22 @@ public inline fun STM.alterHamtWithHash( } } -public fun STM.newHamt(): Hamt = Hamt(newTVar(arrayOfNulls(ARR_SIZE))) +internal fun STM.newHamt(): Hamt = Hamt(newTVar(arrayOfNulls(ARR_SIZE))) -public sealed class Branch { - public data class Branches(val sub: Hamt) : Branch() - public data class Leaf(val hash: Int, val value: Array) : Branch() +internal sealed class Branch { + data class Branches(val sub: Hamt) : Branch() + data class Leaf(val hash: Int, val value: Array) : Branch() + + companion object { + fun leaf(hash: Int, vararg value: A): Leaf = Leaf(hash, value) as Leaf + } } -public const val ARR_SIZE: Int = 32 // 2^DEPTH_STEP -public const val DEPTH_STEP: Int = 5 -public const val MASK: Int = 1.shl(DEPTH_STEP) - 1 +internal const val ARR_SIZE: Int = 32 // 2^DEPTH_STEP +internal const val DEPTH_STEP: Int = 5 +internal const val MASK: Int = 1.shl(DEPTH_STEP) - 1 -public fun Int.index(): Int = MASK.and(this) -public fun Int.atDepth(d: Int): Int = shr(d) -public fun Int.indexAtDepth(d: Int): Int = atDepth(d).index() -public fun Int.nextDepth(): Int = this + DEPTH_STEP +internal fun Int.index(): Int = MASK.and(this) +internal fun Int.atDepth(d: Int): Int = shr(d) +internal fun Int.indexAtDepth(d: Int): Int = atDepth(d).index() +internal fun Int.nextDepth(): Int = this + DEPTH_STEP diff --git a/arrow-libs/fx/arrow-fx-stm/src/commonMain/kotlin/arrow/fx/stm/internal/Impl.kt b/arrow-libs/fx/arrow-fx-stm/src/commonMain/kotlin/arrow/fx/stm/internal/Impl.kt index 327d6a68173..07e7e3aa063 100644 --- a/arrow-libs/fx/arrow-fx-stm/src/commonMain/kotlin/arrow/fx/stm/internal/Impl.kt +++ b/arrow-libs/fx/arrow-fx-stm/src/commonMain/kotlin/arrow/fx/stm/internal/Impl.kt @@ -10,7 +10,7 @@ import kotlin.coroutines.Continuation * A STMFrame keeps the reads and writes performed by a transaction. * It may have a parent which is only used for read lookups. */ -internal class STMFrame(val parent: STMFrame? = null) : STM { +internal class STMFrame(private val parent: STMFrame? = null) : STM { class Entry(var initialVal: Any?, var newVal: Any?) { object NO_CHANGE @@ -19,7 +19,7 @@ internal class STMFrame(val parent: STMFrame? = null) : STM { fun isWrite(): Boolean = newVal !== NO_CHANGE - fun update(v: Any?): Unit { + fun update(v: Any?) { newVal = if (initialVal === v) NO_CHANGE else v } @@ -31,7 +31,7 @@ internal class STMFrame(val parent: STMFrame? = null) : STM { /** * Helper to search the entire hierarchy for stored previous reads */ - private fun readVar(v: TVar): Any? = + private fun readVar(v: TVar): Any = accessMap[v]?.getValue() ?: parent?.readVar(v) ?: Entry.NOT_PRESENT override fun retry(): Nothing = throw RetryException @@ -56,18 +56,18 @@ internal class STMFrame(val parent: STMFrame? = null) : STM { // If we are already invalid here there is no point in continuing. if (frame.validate()) { this@STMFrame.merge(frame) - return@runLocal res as A + return res } } catch (ignored: RetryException) { if (frame.validate()) { this@STMFrame.mergeReads(frame) - return@runLocal onRetry() + return onRetry() } } catch (e: Throwable) { // An invalid frame retries even if it throws, so our sub-frame also needs to handle this correctly if (frame.validate()) { this@STMFrame.mergeReads(frame) - return@runLocal onError(e) + return onError(e) } } } @@ -87,8 +87,11 @@ internal class STMFrame(val parent: STMFrame? = null) : STM { * * If we have not seen this variable before we add a read which stores it in the read set as well. */ - override fun TVar.write(a: A): Unit = - accessMap[this as TVar]?.update(a) ?: readI().let { accessMap[this] = Entry(it, a) } + @Suppress("UNCHECKED_CAST") + override fun TVar.write(a: A) { + this as TVar + accessMap[this]?.update(a) ?: readI().let { accessMap[this] = Entry(it, a) } + } internal fun validate(): Boolean = accessMap.all { (tv, entry) -> tv.value === entry.initialVal } @@ -139,11 +142,11 @@ internal class STMFrame(val parent: STMFrame? = null) : STM { return true } - private fun mergeReads(other: STMFrame): Unit { + private fun mergeReads(other: STMFrame) { accessMap.putAll(other.accessMap.filter { (_, e) -> e.isWrite().not() }) } - private fun merge(other: STMFrame): Unit { + private fun merge(other: STMFrame) { accessMap.putAll(other.accessMap) } } @@ -188,7 +191,7 @@ internal class STMTransaction(val f: STM.() -> A) { if (frame.accessMap.isEmpty()) throw BlockedIndefinitely() val registered = mutableListOf>() - suspendCancellableCoroutine susp@{ k -> + suspendCancellableCoroutine susp@{ k -> cont.set(k) frame.accessMap diff --git a/arrow-libs/fx/arrow-fx-stm/src/jvmMain/kotlin/arrow/fx/stm/internal/RetryException.kt b/arrow-libs/fx/arrow-fx-stm/src/jvmMain/kotlin/arrow/fx/stm/internal/RetryException.kt index 878222f45a2..6545547486b 100644 --- a/arrow-libs/fx/arrow-fx-stm/src/jvmMain/kotlin/arrow/fx/stm/internal/RetryException.kt +++ b/arrow-libs/fx/arrow-fx-stm/src/jvmMain/kotlin/arrow/fx/stm/internal/RetryException.kt @@ -1,5 +1,6 @@ package arrow.fx.stm.internal public actual object RetryException : Throwable("Arrow STM Retry. This should always be caught by arrow internally. Please report this as a bug if that is not the case!") { + private fun readResolve(): Any = RetryException override fun fillInStackTrace(): Throwable { return this } }