Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

deprecate arrow.continuation #2672

Merged
merged 5 commits into from Feb 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -1,18 +1,22 @@
package arrow.continuations

import arrow.continuations.generic.DelimitedScope
import arrow.continuations.generic.deprecateArrowContinuation

@Deprecated(deprecateArrowContinuation)
public fun interface Effect<F> {
public fun control(): DelimitedScope<F>

public companion object {
@Deprecated("$deprecateArrowContinuation Here one can use effect { } directly")
public suspend inline fun <Eff : Effect<*>, F, A> suspended(
crossinline eff: (DelimitedScope<F>) -> Eff,
crossinline just: (A) -> F,
crossinline f: suspend Eff.() -> A,
): F =
Reset.suspended { just(f(eff(this))) }

@Deprecated("$deprecateArrowContinuation Here one can use eagerEffect { } directly")
public inline fun <Eff : Effect<*>, F, A> restricted(
crossinline eff: (DelimitedScope<F>) -> Eff,
crossinline just: (A) -> F,
Expand Down
Expand Up @@ -6,9 +6,11 @@ import arrow.continuations.generic.DelimContScope
import arrow.continuations.generic.RestrictedScope
import arrow.continuations.generic.SuspendMonadContinuation
import arrow.continuations.generic.SuspendedScope
import arrow.continuations.generic.deprecateArrowContinuation
import kotlin.coroutines.intrinsics.suspendCoroutineUninterceptedOrReturn

@PublishedApi
@Deprecated(deprecateArrowContinuation)
internal object Reset {
/**
* Allows for building suspending single-shot computation blocks.
Expand All @@ -21,6 +23,7 @@ internal object Reset {
* use `Either.catch`, `Validated.catch` etc or `e.nonFatalOrThrow()`
* to ensure you're not catching `ShortCircuit`.
*/
@Deprecated(deprecateArrowContinuation)
public suspend fun <A> suspended(block: suspend SuspendedScope<A>.() -> A): A =
suspendCoroutineUninterceptedOrReturn { cont ->
SuspendMonadContinuation(cont, block)
Expand All @@ -32,6 +35,7 @@ internal object Reset {
* For short-circuiting, or shifting, `@RestrictSuspension` state machine is used.
* This doesn't allow nesting of computation blocks, or foreign suspension.
*/
@Deprecated(deprecateArrowContinuation)
// TODO This should be @RestrictSuspension but that breaks because a superclass is not considered to be correct scope
fun <A> restricted(block: suspend RestrictedScope<A>.() -> A): A =
DelimContScope(block).invoke()
Expand Down
@@ -1,5 +1,6 @@
package arrow.continuations.generic

@Deprecated("$deprecateArrowContinuation The AtomicRef APIs have been moved to arrow.core.generic", ReplaceWith("AtomicRef<V>", "arrow.core.generic.AtomicRef"))
public expect class AtomicRef<V>(initialValue: V) {
public fun get(): V
public fun set(value: V)
Expand All @@ -15,12 +16,14 @@ public expect class AtomicRef<V>(initialValue: V) {
/**
* Infinite loop that reads this atomic variable and performs the specified [action] on its value.
*/
@Deprecated("$deprecateArrowContinuation The AtomicRef APIs have been moved to arrow.core.generic", ReplaceWith("loop(action)", "arrow.core.generic.loop"))
public inline fun <V> AtomicRef<V>.loop(action: (V) -> Unit): Nothing {
while (true) {
action(get())
}
}

@Deprecated("$deprecateArrowContinuation The AtomicRef APIs have been moved to arrow.core.generic", ReplaceWith("update(function)", "arrow.core.generic.update"))
public inline fun <V> AtomicRef<V>.update(function: (V) -> V) {
while (true) {
val cur = get()
Expand All @@ -32,6 +35,7 @@ public inline fun <V> AtomicRef<V>.update(function: (V) -> V) {
/**
* Updates variable atomically using the specified [function] of its value and returns its old value.
*/
@Deprecated("$deprecateArrowContinuation The AtomicRef APIs have been moved to arrow.core.generic", ReplaceWith("getAndUpdate(function)", "arrow.core.generic.getAndUpdate"))
public inline fun <V> AtomicRef<V>.getAndUpdate(function: (V) -> V): V {
while (true) {
val cur = get()
Expand All @@ -43,6 +47,7 @@ public inline fun <V> AtomicRef<V>.getAndUpdate(function: (V) -> V): V {
/**
* Updates variable atomically using the specified [function] of its value and returns its new value.
*/
@Deprecated("$deprecateArrowContinuation The AtomicRef APIs have been moved to arrow.core.generic", ReplaceWith("updateAndGet", "arrow.core.generic.updateAndGet"))
public inline fun <V> AtomicRef<V>.updateAndGet(function: (V) -> V): V {
while (true) {
val cur = get()
Expand Down
Expand Up @@ -6,4 +6,8 @@ package arrow.continuations.generic
* and `arrow.core.NonFatal` does not catch this [Throwable].
* Thus by extension `Either.catch` and `Validated.catch` also don't catch [ControlThrowable].
*/
@Deprecated(deprecateArrowContinuation)
public expect open class ControlThrowable() : Throwable

internal const val deprecateArrowContinuation: String =
"arrow.continuation is being discontinued and will be removed in the next version in favor of the Effect/ EagerEffect Runtime. If you depend on low-level APIs as in arrow.continuation, feel free to write us in the Kotlin Slack channel for guidance."
Expand Up @@ -3,13 +3,15 @@ package arrow.continuations.generic
/**
* Base interface for a continuation
*/
@Deprecated(deprecateArrowContinuation)
public interface DelimitedContinuation<A, R> {
public suspend operator fun invoke(a: A): R
}

/**
* Base interface for our scope.
*/
@Deprecated(deprecateArrowContinuation)
public interface DelimitedScope<R> {

/**
Expand All @@ -18,6 +20,7 @@ public interface DelimitedScope<R> {
public suspend fun <A> shift(r: R): A
}

@Deprecated(deprecateArrowContinuation)
public interface RestrictedScope<R> : DelimitedScope<R> {
/**
* Capture the continuation and pass it to [f].
Expand All @@ -27,4 +30,5 @@ public interface RestrictedScope<R> : DelimitedScope<R> {
public override suspend fun <A> shift(r: R): A = shift { r }
}

@Deprecated(deprecateArrowContinuation)
public interface SuspendedScope<R> : DelimitedScope<R>
@@ -1,3 +1,4 @@
package arrow.continuations.generic

@Deprecated(deprecateArrowContinuation)
public class ShortCircuit internal constructor(internal val token: Token, public val raiseValue: Any?) : ControlThrowable()
@@ -1,6 +1,7 @@
package arrow.continuations.generic

/** Represents a unique identifier using object equality. */
@Deprecated(deprecateArrowContinuation)
internal class Token {
override fun toString(): String = "Token(${hashCode().toString(16)})"
}
@@ -1,5 +1,6 @@
package arrow.continuations.generic

@Deprecated(deprecateArrowContinuation)
public actual class AtomicRef<V> actual constructor(initialValue: V) {
private var internalValue: V = initialValue

Expand Down
Expand Up @@ -6,4 +6,5 @@ package arrow.continuations.generic
* and `arrow.core.NonFatal` does not catch this [Throwable].
* Thus by extension `Either.catch` and `Validated.catch` also don't catch [ControlThrowable.kt].
*/
@Deprecated(deprecateArrowContinuation)
public actual open class ControlThrowable : Throwable()
Expand Up @@ -4,4 +4,5 @@ package arrow.continuations.generic

import java.util.concurrent.atomic.AtomicReference

@Deprecated(deprecateArrowContinuation)
public actual typealias AtomicRef<V> = AtomicReference<V>
Expand Up @@ -7,6 +7,7 @@ package arrow.continuations.generic
* and `arrow.core.NonFatal` does not catch this [Throwable].
* Thus by extension `Either.catch` and `Validated.catch` also don't catch [ControlThrowable.kt].
*/
@Deprecated(deprecateArrowContinuation)
public actual open class ControlThrowable : Throwable() {
override fun fillInStackTrace(): Throwable = this
}
Expand Up @@ -4,6 +4,7 @@ import kotlin.native.concurrent.AtomicReference
import kotlin.native.concurrent.freeze
import kotlin.native.concurrent.isFrozen

@Deprecated(deprecateArrowContinuation)
public actual class AtomicRef<V> actual constructor(initialValue: V) {
private val atom = AtomicReference(initialValue.freeze())
public actual fun get(): V = atom.value
Expand Down
Expand Up @@ -6,4 +6,5 @@ package arrow.continuations.generic
* and `arrow.core.NonFatal` does not catch this [Throwable].
* Thus by extension `Either.catch` and `Validated.catch` also don't catch [ControlThrowable].
*/
@Deprecated(deprecateArrowContinuation)
public actual open class ControlThrowable : Throwable()
7 changes: 7 additions & 0 deletions arrow-libs/core/arrow-core/api/arrow-core.api
Expand Up @@ -2511,6 +2511,13 @@ public final class arrow/core/computations/result {
public final fun invoke-IoAF18A (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
}

public final class arrow/core/continuations/AtomicRefKt {
public static final fun getAndUpdate (Ljava/util/concurrent/atomic/AtomicReference;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
public static final fun loop (Ljava/util/concurrent/atomic/AtomicReference;Lkotlin/jvm/functions/Function1;)Ljava/lang/Void;
public static final fun update (Ljava/util/concurrent/atomic/AtomicReference;Lkotlin/jvm/functions/Function1;)V
public static final fun updateAndGet (Ljava/util/concurrent/atomic/AtomicReference;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
}

public final class arrow/core/continuations/Eager : arrow/core/continuations/ShiftCancellationException {
public fun <init> (Larrow/core/continuations/Token;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)V
public final fun getRecover ()Lkotlin/jvm/functions/Function1;
Expand Down
@@ -0,0 +1,52 @@
package arrow.core.continuations

public expect class AtomicRef<V>(initialValue: V) {
public fun get(): V
public fun set(value: V)
public fun getAndSet(value: V): 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'.
*/
public fun compareAndSet(expected: V, new: V): Boolean
}

/**
* Infinite loop that reads this atomic variable and performs the specified [action] on its value.
*/
public inline fun <V> AtomicRef<V>.loop(action: (V) -> Unit): Nothing {
while (true) {
action(get())
}
}

public inline fun <V> AtomicRef<V>.update(function: (V) -> V) {
while (true) {
val cur = get()
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> AtomicRef<V>.getAndUpdate(function: (V) -> V): V {
while (true) {
val cur = get()
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> AtomicRef<V>.updateAndGet(function: (V) -> V): V {
while (true) {
val cur = get()
val upd = function(cur)
if (compareAndSet(cur, upd)) return upd
}
}
@@ -1,7 +1,5 @@
package arrow.core.continuations

import arrow.continuations.generic.AtomicRef
import arrow.continuations.generic.updateAndGet
import arrow.core.EmptyValue
import arrow.core.Ior
import arrow.core.identity
Expand Down
Expand Up @@ -2,8 +2,8 @@

package arrow.core

import arrow.continuations.generic.AtomicRef
import arrow.continuations.generic.loop
import arrow.core.continuations.AtomicRef
import arrow.core.continuations.loop
import kotlin.jvm.JvmName

/**
Expand Down
@@ -0,0 +1,30 @@
package arrow.core.continuations

public actual class AtomicRef<V> actual constructor(initialValue: V) {
private var internalValue: V = initialValue

/**
* Compare current value with expected and set to new if they're the same. Note, 'compare' is checking
* the actual object id, not 'equals'.
*/
public actual fun compareAndSet(expected: V, new: V): Boolean {
return if (expected === internalValue) {
internalValue = new
true
} else {
false
}
}

public actual fun getAndSet(value: V): V {
val oldValue = internalValue
internalValue = value
return oldValue
}

public actual fun get(): V = internalValue

public actual fun set(value: V) {
internalValue = value
}
}
@@ -0,0 +1,7 @@
@file:JvmName("AtomicReferenceActual")

package arrow.core.continuations

import java.util.concurrent.atomic.AtomicReference

public actual typealias AtomicRef<V> = AtomicReference<V>
@@ -0,0 +1,30 @@
package arrow.core.continuations

import kotlin.native.concurrent.AtomicReference
import kotlin.native.concurrent.freeze
import kotlin.native.concurrent.isFrozen

public actual class AtomicRef<V> actual constructor(initialValue: V) {
private val atom = AtomicReference(initialValue.freeze())
public actual fun get(): V = atom.value

public actual fun set(value: V) {
atom.value = value.freeze()
}

public actual 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
}
}

/**
* Compare current value with expected and set to new if they're the same. Note, 'compare' is checking
* the actual object id, not 'equals'.
*/
public actual fun compareAndSet(expected: V, new: V): Boolean =
atom.compareAndSet(expected, new.freeze())
}
@@ -1,6 +1,6 @@
package arrow.fx.coroutines

import arrow.continuations.generic.AtomicRef
import arrow.core.continuations.AtomicRef
import java.util.concurrent.ThreadFactory
import kotlin.coroutines.CoroutineContext

Expand Down
@@ -1,6 +1,6 @@
package arrow.fx.coroutines

import arrow.continuations.generic.AtomicRef
import arrow.core.continuations.AtomicRef

/**
* An [Atomic] with an initial value of [A].
Expand Down
@@ -1,7 +1,7 @@
package arrow.fx.coroutines

import arrow.continuations.generic.AtomicRef
import arrow.core.Either
import arrow.core.continuations.AtomicRef
import arrow.core.identity
import arrow.fx.coroutines.CircuitBreaker.State.Closed
import arrow.fx.coroutines.CircuitBreaker.State.HalfOpen
Expand Down
@@ -1,7 +1,7 @@
package arrow.fx.coroutines

import arrow.continuations.generic.AtomicRef
import arrow.continuations.generic.update
import arrow.core.continuations.AtomicRef
import arrow.core.continuations.update
import arrow.core.NonEmptyList
import arrow.core.ValidatedNel
import arrow.core.identity
Expand Down
@@ -1,8 +1,8 @@
package arrow.fx.stm

import arrow.continuations.generic.AtomicRef
import arrow.continuations.generic.update
import arrow.continuations.generic.updateAndGet
import arrow.core.continuations.AtomicRef
import arrow.core.continuations.update
import arrow.core.continuations.updateAndGet
import arrow.fx.stm.internal.STMFrame
import arrow.fx.stm.internal.STMTransaction
import kotlin.coroutines.resume
Expand Down
@@ -1,6 +1,6 @@
package arrow.fx.stm.internal

import arrow.continuations.generic.AtomicRef
import arrow.core.continuations.AtomicRef
import arrow.fx.stm.STM
import arrow.fx.stm.TVar
import kotlinx.coroutines.suspendCancellableCoroutine
Expand Down