Skip to content

Commit

Permalink
Merge branch 'main' into arrow-2
Browse files Browse the repository at this point in the history
  • Loading branch information
serras committed Apr 16, 2024
2 parents d5b188c + af99eb4 commit 0c0a85e
Show file tree
Hide file tree
Showing 7 changed files with 60 additions and 120 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/githubpages.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
58 changes: 0 additions & 58 deletions arrow-libs/fx/arrow-fx-stm/api/arrow-fx-stm.api
Original file line number Diff line number Diff line change
Expand Up @@ -239,64 +239,6 @@ public final class arrow/fx/stm/internal/BlockedIndefinitely : java/lang/Throwab
public fun <init> ()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 <init> (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 <init> (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 <init> (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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 <A> TVar<A>.write(a: A): Unit
public fun <A> TVar<A>.write(a: A)

/**
* Modify the value of a [TVar]
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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 <A> TQueue<A>.removeAll(pred: (A) -> Boolean): Unit {
public fun <A> TQueue<A>.removeAll(pred: (A) -> Boolean) {
reads.modify { it.filter(pred) }
writes.modify { it.filter(pred) }
}
Expand Down Expand Up @@ -1333,7 +1333,7 @@ public interface STM {
* ```
* <!--- KNIT example-stm-46.kt -->
*/
public fun <K, V> TMap<K, V>.insert(k: K, v: V): Unit {
public fun <K, V> TMap<K, V>.insert(k: K, v: V) {
alterHamtWithHash(hamt, hashFn(k), { it.first == k }) { k to v }
}

Expand Down Expand Up @@ -1398,8 +1398,8 @@ public interface STM {
* ```
* <!--- KNIT example-stm-49.kt -->
*/
public fun <K, V> TMap<K, V>.update(k: K, fn: (V) -> V): Unit {
alterHamtWithHash(hamt, hashFn(k), { it.first == k }) { it?.second?.let(fn)?.let { k to it } }
public fun <K, V> TMap<K, V>.update(k: K, fn: (V) -> V) {
alterHamtWithHash(hamt, hashFn(k), { it.first == k }) { it?.second?.let(fn)?.let { r -> k to r } }
}

/**
Expand All @@ -1421,7 +1421,7 @@ public interface STM {
* ```
* <!--- KNIT example-stm-50.kt -->
*/
public fun <K, V> TMap<K, V>.remove(k: K): Unit {
public fun <K, V> TMap<K, V>.remove(k: K) {
alterHamtWithHash(hamt, hashFn(k), { it.first == k }) { null }
}

Expand Down Expand Up @@ -1467,7 +1467,7 @@ public interface STM {
* ```
* <!--- KNIT example-stm-52.kt -->
*/
public fun <A> TSet<A>.insert(a: A): Unit {
public fun <A> TSet<A>.insert(a: A) {
alterHamtWithHash(hamt, hashFn(a), { it == a }) { a }
}

Expand Down Expand Up @@ -1510,7 +1510,7 @@ public interface STM {
* ```
* <!--- KNIT example-stm-54.kt -->
*/
public fun <A> TSet<A>.remove(a: A): Unit {
public fun <A> TSet<A>.remove(a: A) {
alterHamtWithHash(hamt, hashFn(a), { it == a }) { null }
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,21 @@ 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<A>(val branches: TVar<Array<Branch<A>?>>) {
public companion object {
public suspend fun <A> new(): Hamt<A> = Hamt(TVar.new(arrayOfNulls(ARR_SIZE)))
internal data class Hamt<A>(val branches: TVar<Array<Branch<A>?>>) {
companion object {
suspend fun <A> new(): Hamt<A> = Hamt(TVar.new(arrayOfNulls(ARR_SIZE)))
}
}

public inline fun <A> STM.lookupHamtWithHash(hmt: Hamt<A>, hash: Int, test: (A) -> Boolean): A? {
internal fun <A> STM.lookupHamtWithHash(hmt: Hamt<A>, hash: Int, test: (A) -> Boolean): A? {
var depth = 0
var hamt = hmt
while (true) {
val branchInd = hash.indexAtDepth(depth)
val branches = hamt.branches.read()
when (val branch = branches[branchInd]) {
null -> return null
is Branch.Leaf -> return (branch.value as Array<A>).find(test)
is Branch.Leaf -> return branch.value.find(test)
is Branch.Branches -> {
depth = depth.nextDepth()
hamt = branch.sub
Expand All @@ -33,7 +33,7 @@ public inline fun <A> STM.lookupHamtWithHash(hmt: Hamt<A>, hash: Int, test: (A)
}
}

public fun <A> STM.pair(depth: Int, hash1: Int, branch1: Branch<A>, hash2: Int, branch2: Branch<A>): Hamt<A> {
internal fun <A> STM.pair(depth: Int, hash1: Int, branch1: Branch<A>, hash2: Int, branch2: Branch<A>): Hamt<A> {
val branchInd1 = hash1.indexAtDepth(depth)
val branchInd2 = hash2.indexAtDepth(depth)
val branches = arrayOfNulls<Branch<A>>(ARR_SIZE)
Expand All @@ -47,9 +47,9 @@ public fun <A> STM.pair(depth: Int, hash1: Int, branch1: Branch<A>, hash2: Int,
return Hamt(newTVar(branches))
}

public fun <A> STM.clearHamt(hamt: Hamt<A>): Unit = hamt.branches.write(arrayOfNulls(ARR_SIZE))
// internal fun <A> STM.clearHamt(hamt: Hamt<A>): Unit = hamt.branches.write(arrayOfNulls(ARR_SIZE))

public inline fun <A> STM.alterHamtWithHash(
internal fun <A> STM.alterHamtWithHash(
hamt: Hamt<A>,
hash: Int,
test: (A) -> Boolean,
Expand All @@ -64,46 +64,35 @@ public inline fun <A> 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<A>).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<Any?> = 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<A>
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<Any?>)
hmt.branches.write(new)
return true
Branch.Leaf(hash, newLeafArr)
}
}
}
Expand All @@ -113,15 +102,16 @@ public inline fun <A> 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()
Expand All @@ -131,18 +121,22 @@ public inline fun <A> STM.alterHamtWithHash(
}
}

public fun <A> STM.newHamt(): Hamt<A> = Hamt(newTVar(arrayOfNulls(ARR_SIZE)))
internal fun <A> STM.newHamt(): Hamt<A> = Hamt(newTVar(arrayOfNulls(ARR_SIZE)))

public sealed class Branch<out A> {
public data class Branches<A>(val sub: Hamt<A>) : Branch<A>()
public data class Leaf<A>(val hash: Int, val value: Array<Any?>) : Branch<A>()
internal sealed class Branch<A> {
data class Branches<A>(val sub: Hamt<A>) : Branch<A>()
data class Leaf<A>(val hash: Int, val value: Array<A>) : Branch<A>()

companion object {
fun <A> leaf(hash: Int, vararg value: A): Leaf<A> = Leaf(hash, value) as Leaf<A>
}
}

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
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,11 @@ internal class STMFrame(private 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 <A> TVar<A>.write(a: A): Unit =
accessMap[this as TVar<Any?>]?.update(a) ?: readI().let { accessMap[this] = Entry(it, a) }
@Suppress("UNCHECKED_CAST")
override fun <A> TVar<A>.write(a: A) {
this as TVar<Any?>
accessMap[this]?.update(a) ?: readI().let { accessMap[this] = Entry(it, a) }
}

internal fun validate(): Boolean =
accessMap.all { (tv, entry) -> tv.value === entry.initialVal }
Expand Down
Original file line number Diff line number Diff line change
@@ -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 }
}
4 changes: 2 additions & 2 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,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"

Expand Down

0 comments on commit 0c0a85e

Please sign in to comment.