-
Notifications
You must be signed in to change notification settings - Fork 451
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Atomic module, and StateShift (#2817)
* Two small deprecations * Add Atomic module, and StateShift. Implement ior through StateShift * Fix build * Fix atomic knit * Fix knit attempt #2 * Update API files * Remove references to shift
- Loading branch information
Showing
47 changed files
with
465 additions
and
821 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
public abstract interface class arrow/atomic/Atomic { | ||
public abstract fun compareAndSet (Ljava/lang/Object;Ljava/lang/Object;)Z | ||
public abstract fun getAndSet (Ljava/lang/Object;)Ljava/lang/Object; | ||
public abstract fun getValue ()Ljava/lang/Object; | ||
public abstract fun setAndGet (Ljava/lang/Object;)Ljava/lang/Object; | ||
public abstract fun setValue (Ljava/lang/Object;)V | ||
} | ||
|
||
public final class arrow/atomic/AtomicActual { | ||
public static final fun Atomic (Ljava/lang/Object;)Larrow/atomic/Atomic; | ||
} | ||
|
||
public final class arrow/atomic/AtomicKt { | ||
public static final fun getAndUpdate (Larrow/atomic/Atomic;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; | ||
public static final fun loop (Larrow/atomic/Atomic;Lkotlin/jvm/functions/Function1;)Ljava/lang/Void; | ||
public static final fun tryUpdate (Larrow/atomic/Atomic;Lkotlin/jvm/functions/Function1;)Z | ||
public static final fun update (Larrow/atomic/Atomic;Lkotlin/jvm/functions/Function1;)V | ||
public static final fun updateAndGet (Larrow/atomic/Atomic;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
plugins { | ||
id(libs.plugins.kotlin.multiplatform.get().pluginId) | ||
alias(libs.plugins.arrowGradleConfig.kotlin) | ||
alias(libs.plugins.arrowGradleConfig.publish) | ||
} | ||
|
||
apply(plugin = "io.kotest.multiplatform") | ||
apply(from = property("TEST_COVERAGE")) | ||
apply(from = property("ANIMALSNIFFER_MPP")) | ||
|
||
val enableCompatibilityMetadataVariant = | ||
providers.gradleProperty("kotlin.mpp.enableCompatibilityMetadataVariant") | ||
.forUseAtConfigurationTime().orNull?.toBoolean() == true | ||
|
||
if (enableCompatibilityMetadataVariant) { | ||
tasks.withType<Test>().configureEach { | ||
exclude("**/*") | ||
} | ||
} | ||
|
||
kotlin { | ||
sourceSets { | ||
commonMain { | ||
dependencies { | ||
api(libs.kotlin.stdlibCommon) | ||
} | ||
} | ||
|
||
jvmMain { | ||
dependencies { | ||
implementation(libs.kotlin.stdlibJDK8) | ||
} | ||
} | ||
|
||
jvmTest { | ||
dependencies { | ||
implementation(projects.arrowFxCoroutines) | ||
} | ||
} | ||
|
||
jsMain { | ||
dependencies { | ||
implementation(libs.kotlin.stdlibJS) | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# Maven publishing configuration | ||
pom.name=Arrow Atomic | ||
# Build configuration | ||
kapt.incremental.apt=false |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
knit.package=arrow.atomic.examples | ||
knit.dir=src/jvmTest/kotlin/examples/ | ||
|
||
test.package=arrow.atomic.examples.test | ||
test.dir=src/jvmTest/kotlin/examples/autogenerated/ |
74 changes: 74 additions & 0 deletions
74
arrow-libs/core/arrow-atomic/src/commonMain/kotlin/arrow/atomic/Atomic.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
package arrow.atomic | ||
|
||
public expect fun <A> Atomic(initialValue: A): Atomic<A> | ||
|
||
/** | ||
* [Atomic] value of [A]. | ||
* | ||
* ```kotlin | ||
* import arrow.atomic.Atomic | ||
* import arrow.atomic.update | ||
* import arrow.fx.coroutines.parTraverse | ||
* suspend fun main() { | ||
* val count = Atomic(0) | ||
* (0 until 20_000).parTraverse { | ||
* count.update(Int::inc) | ||
* } | ||
* println(count.value) | ||
* } | ||
* ``` | ||
* <!--- KNIT example-atomic-01.kt --> | ||
* | ||
* [Atomic] also offers some other interesting operators such as [loop], [update], [tryUpdate], etc. | ||
*/ | ||
public interface Atomic<A> { | ||
public var value: A | ||
public fun getAndSet(value: A): A | ||
public fun setAndGet(value: A): A | ||
public fun compareAndSet(expected: A, new: A): Boolean | ||
} | ||
|
||
/** | ||
* Infinite loop that reads this atomic variable and performs the specified [action] on its value. | ||
*/ | ||
public inline fun <V> Atomic<V>.loop(action: (V) -> Unit): Nothing { | ||
while (true) { | ||
action(value) | ||
} | ||
} | ||
|
||
public fun <V> Atomic<V>.tryUpdate(function: (V) -> V): Boolean { | ||
val cur = value | ||
val upd = function(cur) | ||
return compareAndSet(cur, upd) | ||
} | ||
|
||
public inline fun <V> Atomic<V>.update(function: (V) -> V) { | ||
while (true) { | ||
val cur = value | ||
val upd = function(cur) | ||
if (compareAndSet(cur, upd)) return | ||
} | ||
} | ||
|
||
/** | ||
* Updates variable atomically using the specified [function] of its value and returns its old value. | ||
*/ | ||
public inline fun <V> Atomic<V>.getAndUpdate(function: (V) -> V): V { | ||
while (true) { | ||
val cur = value | ||
val upd = function(cur) | ||
if (compareAndSet(cur, upd)) return cur | ||
} | ||
} | ||
|
||
/** | ||
* Updates variable atomically using the specified [function] of its value and returns its new value. | ||
*/ | ||
public inline fun <V> Atomic<V>.updateAndGet(function: (V) -> V): V { | ||
while (true) { | ||
val cur = value | ||
val upd = function(cur) | ||
if (compareAndSet(cur, upd)) return upd | ||
} | ||
} |
38 changes: 38 additions & 0 deletions
38
arrow-libs/core/arrow-atomic/src/jsMain/kotlin/arrow/atomic/Atomic.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
package arrow.atomic | ||
|
||
public actual fun <A> Atomic(initialValue: A): Atomic<A> = | ||
AtomicRef(initialValue) | ||
|
||
private class AtomicRef<V>(private var internalValue: V) : Atomic<V> { | ||
|
||
/** | ||
* Compare current value with expected and set to new if they're the same. Note, 'compare' is checking | ||
* the actual object id, not 'equals'. | ||
*/ | ||
override fun compareAndSet(expected: V, new: V): Boolean { | ||
return if (expected === internalValue) { | ||
internalValue = new | ||
true | ||
} else { | ||
false | ||
} | ||
} | ||
|
||
override fun getAndSet(value: V): V { | ||
val oldValue = internalValue | ||
internalValue = value | ||
return oldValue | ||
} | ||
|
||
override fun setAndGet(value: V): V { | ||
this.internalValue = value | ||
return value | ||
} | ||
|
||
|
||
override var value: V | ||
get() = internalValue | ||
set(value) { | ||
internalValue = value | ||
} | ||
} |
26 changes: 26 additions & 0 deletions
26
arrow-libs/core/arrow-atomic/src/jvmMain/kotlin/arrow/atomic/Atomic.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
@file:JvmName("AtomicActual") | ||
|
||
package arrow.atomic | ||
|
||
import java.util.concurrent.atomic.AtomicReference | ||
|
||
public actual fun <A> Atomic(initialValue: A): Atomic<A> = | ||
AtomicRef(AtomicReference(initialValue)) | ||
|
||
private class AtomicRef<A> constructor(private val atom: AtomicReference<A>) : Atomic<A> { | ||
|
||
override var value: A | ||
get() = atom.get() | ||
set(value) { | ||
atom.set(value) | ||
} | ||
|
||
override fun compareAndSet(expected: A, new: A): Boolean = atom.compareAndSet(expected, new) | ||
|
||
override fun getAndSet(value: A): A = atom.getAndSet(value) | ||
|
||
override fun setAndGet(value: A): A { | ||
atom.set(value) | ||
return value | ||
} | ||
} |
10 changes: 5 additions & 5 deletions
10
...Test/kotlin/examples/example-atomic-01.kt → ...Test/kotlin/examples/example-atomic-01.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,13 @@ | ||
// This file was automatically generated from Atomic.kt by Knit tool. Do not edit. | ||
package arrow.fx.coroutines.examples.exampleAtomic01 | ||
|
||
import arrow.fx.coroutines.* | ||
package arrow.atomic.examples.exampleAtomic01 | ||
|
||
import arrow.atomic.Atomic | ||
import arrow.atomic.update | ||
import arrow.fx.coroutines.parTraverse | ||
suspend fun main() { | ||
val count = Atomic(0) | ||
|
||
(0 until 20_000).parTraverse { | ||
count.update(Int::inc) | ||
} | ||
println(count.get()) | ||
println(count.value) | ||
} |
35 changes: 35 additions & 0 deletions
35
arrow-libs/core/arrow-atomic/src/nativeMain/kotlin/arrow/atomic/Atomic.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package arrow.atomic | ||
|
||
import kotlin.native.concurrent.AtomicReference | ||
import kotlin.native.concurrent.freeze | ||
import kotlin.native.concurrent.isFrozen | ||
|
||
public actual fun <A> Atomic(initialValue: A): Atomic<A> = | ||
AtomicRef(AtomicReference(initialValue.freeze())) | ||
|
||
private class AtomicRef<V>(private val atom: AtomicReference<V>): Atomic<V> { | ||
|
||
override fun getAndSet(value: V): V { | ||
if (atom.isFrozen) value.freeze() | ||
while (true) { | ||
val cur = atom.value | ||
if (cur === value) return cur | ||
if (atom.compareAndSwap(cur, value) === cur) return cur | ||
} | ||
} | ||
|
||
override fun compareAndSet(expected: V, new: V): Boolean = | ||
atom.compareAndSet(expected, new.freeze()) | ||
|
||
override var value: V | ||
get() = atom.value | ||
set(value) { | ||
atom.value = value.freeze() | ||
} | ||
|
||
override fun setAndGet(value: V): V { | ||
this.value = value | ||
return value | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.