SignallingRef

fs2.concurrent.SignallingRef
See theSignallingRef companion object
abstract class SignallingRef[F[_], A] extends Ref[F, A], Signal[F, A]

Pure holder of a single value of type A that can be both read and updated in the effect F.

The update methods have the same semantics as Ref, as well as propagating changes to discrete (with a last-update-wins policy in case of very fast updates).

The access method differs slightly from Ref in that the update function, in the presence of discrete, can return false and need looping even without any other writers.

Attributes

Companion
object
Source
Signal.scala
Graph
Supertypes
trait Signal[F, A]
class Ref[F, A]
trait RefSink[F, A]
trait RefSource[F, A]
trait Serializable
class Object
trait Matchable
class Any
Show all

Members list

Value members

Inherited methods

def access: F[(A, A => F[Boolean])]

Obtains a snapshot of the current value, and a setter for updating it.

Obtains a snapshot of the current value, and a setter for updating it.

The setter attempts to modify the contents from the snapshot to the new value (and return true). If it cannot do this (because the contents changed since taking the snapshot), the setter is a noop and returns false.

Satisfies: r.access.map(_._1) == r.get and r.access.flatMap { case (v, setter) => setter(f(v)) } == r.tryUpdate(f).map(_.isDefined).

Attributes

Inherited from:
Ref
Source
Ref.scala
def changes(implicit eqA: Eq[A]): Signal[F, A]

Returns a signal derived from this one, that drops update events that did not change the value.

Returns a signal derived from this one, that drops update events that did not change the value.

Attributes

Inherited from:
Signal
Source
Signal.scala
def continuous: Stream[F, A]

Returns a stream of the current value of the signal.

Returns a stream of the current value of the signal. An element is always available -- on each pull, the current value is supplied.

Attributes

Inherited from:
Signal
Source
Signal.scala
def discrete: Stream[F, A]

Returns a stream of the current value and subsequent updates to this signal.

Returns a stream of the current value and subsequent updates to this signal.

Even if you are pulling as fast as possible, updates that are very close together may result in only the last update appearing in the stream. In general, when you pull from this stream you may be notified of only the latest update since your last pull. If you want to be notified about every single update, use a Queue or Channel instead.

Attributes

Inherited from:
Signal
Source
Signal.scala
def flatModify[B](f: A => (A, F[B]))(implicit F: MonadCancel[F, _]): F[B]

Like modify but schedules resulting effect right after modification.

Like modify but schedules resulting effect right after modification.

Useful for implementing effectful transition of a state machine, in which an effect is performed based on current state and the state must be updated to reflect that this effect will be performed.

Both modification and finalizer are within a single uncancelable region, to prevent canceled finalizers from leaving the Ref's value permanently out of sync with effects actually performed. if you need cancellation mechanic in finalizer please see flatModifyFull.

Attributes

See also
Inherited from:
Ref
Source
Ref.scala
def flatModifyFull[B](f: (Poll[F], A) => (A, F[B]))(implicit F: MonadCancel[F, _]): F[B]

Like modify but schedules resulting effect right after modification.

Like modify but schedules resulting effect right after modification.

Unlike flatModify finalizer cancellation could be unmasked via supplied Poll. Modification itself is still uncancelable.

When used as part of a state machine, cancelable regions should usually have an onCancel finalizer to update the state to reflect that the effect will not be performed.

Attributes

See also
Inherited from:
Ref
Source
Ref.scala
def flatModifyState[B](state: State[A, F[B]])(implicit F: MonadCancel[F, _]): F[B]

Like modifyState but schedules resulting effect right after state computation & update.

Like modifyState but schedules resulting effect right after state computation & update.

Both modification and finalizer are uncancelable, if you need cancellation mechanic in finalizer please see flatModifyStateFull.

Attributes

See also
Inherited from:
Ref
Source
Ref.scala
def flatModifyStateFull[B](state: Poll[F] => State[A, F[B]])(implicit F: MonadCancel[F, _]): F[B]

Like modifyState but schedules resulting effect right after modification.

Like modifyState but schedules resulting effect right after modification.

Unlike flatModifyState finalizer cancellation could be masked via supplied Poll[F]. Modification itself is still uncancelable.

Attributes

See also
Inherited from:
Ref
Source
Ref.scala
def get: F[A]

Gets the current value of this Signal.

Gets the current value of this Signal.

Attributes

Inherited from:
Signal
Source
Signal.scala
def getAndDiscreteUpdates(implicit F: Concurrent[F]): Resource[F, (A, Stream[F, A])]

Returns the current value of this Signal and a Stream to subscribe to subsequent updates, with the same semantics as discrete.

Returns the current value of this Signal and a Stream to subscribe to subsequent updates, with the same semantics as discrete. The updates stream should be compiled at most once.

Attributes

Inherited from:
Signal
Source
Signal.scala
def getAndSet(a: A): F[A]

Replaces the current value with a, returning the previous value.

Replaces the current value with a, returning the previous value.

Attributes

Inherited from:
Ref
Source
Ref.scala
def getAndUpdate(f: A => A): F[A]

Updates the current value using f and returns the previous value.

Updates the current value using f and returns the previous value.

In case of retries caused by concurrent modifications, the returned value will be the last one before a successful update.

Attributes

Inherited from:
Ref
Source
Ref.scala
def mapK[G[_]](f: FunctionK[F, G])(implicit F: Functor[F]): Ref[G, A]

Modify the context F using transformation f.

Modify the context F using transformation f.

Attributes

Inherited from:
Ref
Source
Ref.scala
def modify[B](f: A => (A, B)): F[B]

Like tryModify but retries until the update has been successfully made.

Like tryModify but retries until the update has been successfully made.

Attributes

Inherited from:
Ref
Source
Ref.scala
def modifyState[B](state: State[A, B]): F[B]

Like tryModifyState but retries the modification until successful.

Like tryModifyState but retries the modification until successful.

Attributes

Inherited from:
Ref
Source
Ref.scala
def set(a: A): F[Unit]

Sets the current value to a.

Sets the current value to a.

The returned action completes after the reference has been successfully set.

Attributes

Inherited from:
RefSink
Source
Ref.scala
def tryModify[B](f: A => (A, B)): F[Option[B]]

Like tryUpdate but allows the update function to return an output value of type B.

Like tryUpdate but allows the update function to return an output value of type B. The returned action completes with None if the value is not updated successfully and Some(b) otherwise.

Attributes

Inherited from:
Ref
Source
Ref.scala
def tryModifyState[B](state: State[A, B]): F[Option[B]]

Update the value of this Ref with a state computation.

Update the value of this Ref with a state computation.

The current value of this Ref is used as the initial state and the computed output state is stored in this Ref after computation completes. If a concurrent modification occurs, None is returned.

Attributes

Inherited from:
Ref
Source
Ref.scala
def tryUpdate(f: A => A): F[Boolean]

Attempts to modify the current value once, returning false if another concurrent modification completes between the time the variable is read and the time it is set.

Attempts to modify the current value once, returning false if another concurrent modification completes between the time the variable is read and the time it is set.

Attributes

Inherited from:
Ref
Source
Ref.scala
def update(f: A => A): F[Unit]

Modifies the current value using the supplied update function.

Modifies the current value using the supplied update function. If another modification occurs between the time the current value is read and subsequently updated, the modification is retried using the new value. Hence, f may be invoked multiple times.

Satisfies: r.update(_ => a) == r.set(a)

Attributes

Inherited from:
Ref
Source
Ref.scala
def updateAndGet(f: A => A): F[A]

Updates the current value using f, and returns the updated value.

Updates the current value using f, and returns the updated value.

Attributes

Inherited from:
Ref
Source
Ref.scala
def waitUntil(p: A => Boolean)(implicit F: Concurrent[F]): F[Unit]

Returns when the condition becomes true, semantically blocking in the meantime.

Returns when the condition becomes true, semantically blocking in the meantime.

This method is particularly useful to transform naive, recursive polling algorithms on the content of a Signal/ SignallingRef into semantically blocking ones. For example, here's how to encode a very simple cache with expiry, pay attention to the definition of view:

trait Refresh[F[_], A] {
 def get: F[A]
}
object Refresh {
 def create[F[_]: Temporal, A](
   action: F[A],
   refreshAfter: A => FiniteDuration,
   defaultExpiry: FiniteDuration
 ): Resource[F, Refresh[F, A]] =
   Resource
     .eval(SignallingRef[F, Option[Either[Throwable, A]]](None))
     .flatMap { state =>
       def refresh: F[Unit] =
         state.set(None) >> action.attempt.flatMap { res =>
           val t = res.map(refreshAfter).getOrElse(defaultExpiry)
           state.set(res.some) >> Temporal[F].sleep(t) >> refresh
         }

       def view = new Refresh[F, A] {
         def get: F[A] = state.get.flatMap {
           case Some(res) => Temporal[F].fromEither(res)
           case None => state.waitUntil(_.isDefined) >> get
         }
       }

       refresh.background.as(view)
     }
}

Note that because Signal prioritizes the latest update when its state is updating very quickly, completion of the F[Unit] might not trigger if the condition becomes true and then false immediately after.

Therefore, natural use cases of waitUntil tend to fall into two categories: - Scenarios where conditions don't change instantly, such as periodic timed processes updating the Signal/SignallingRef. - Scenarios where conditions might change instantly, but the p predicate is monotonic, i.e. if it tests true for an event, it will test true for the following events as well. Examples include waiting for a unique ID stored in a Signal to change, or waiting for the value of the Signal of an ordered Stream[IO, Int] to be greater than a certain number.

Attributes

Inherited from:
Signal
Source
Signal.scala