trait Signal[F[_], A] extends AnyRef
Pure holder of a single value of type A
that can be read in the effect F
.
- Self Type
- Signal[F, A]
- Source
- Signal.scala
- Alphabetic
- By Inheritance
- Signal
- AnyRef
- Any
- Hide All
- Show All
- Public
- Protected
Abstract Value Members
- abstract 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.
- abstract 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
orChannel
instead. - abstract def get: F[A]
Gets the current value of this
Signal
.
Concrete Value Members
- final def !=(arg0: Any): Boolean
- Definition Classes
- AnyRef → Any
- final def ##: Int
- Definition Classes
- AnyRef → Any
- final def ==(arg0: Any): Boolean
- Definition Classes
- AnyRef → Any
- final def asInstanceOf[T0]: T0
- Definition Classes
- Any
- 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.
- def clone(): AnyRef
- Attributes
- protected[lang]
- Definition Classes
- AnyRef
- Annotations
- @throws(classOf[java.lang.CloneNotSupportedException]) @native() @IntrinsicCandidate()
- final def eq(arg0: AnyRef): Boolean
- Definition Classes
- AnyRef
- def equals(arg0: AnyRef): Boolean
- Definition Classes
- AnyRef → Any
- def getAndDiscreteUpdates(implicit F: Concurrent[F]): Resource[F, (A, Stream[F, A])]
Returns the current value of this
Signal
and aStream
to subscribe to subsequent updates, with the same semantics as discrete.Returns the current value of this
Signal
and aStream
to subscribe to subsequent updates, with the same semantics as discrete. The updates stream should be compiled at most once. - final def getClass(): Class[_ <: AnyRef]
- Definition Classes
- AnyRef → Any
- Annotations
- @native() @IntrinsicCandidate()
- def hashCode(): Int
- Definition Classes
- AnyRef → Any
- Annotations
- @native() @IntrinsicCandidate()
- final def isInstanceOf[T0]: Boolean
- Definition Classes
- Any
- final def ne(arg0: AnyRef): Boolean
- Definition Classes
- AnyRef
- final def notify(): Unit
- Definition Classes
- AnyRef
- Annotations
- @native() @IntrinsicCandidate()
- final def notifyAll(): Unit
- Definition Classes
- AnyRef
- Annotations
- @native() @IntrinsicCandidate()
- final def synchronized[T0](arg0: => T0): T0
- Definition Classes
- AnyRef
- def toString(): String
- Definition Classes
- AnyRef → Any
- final def wait(arg0: Long, arg1: Int): Unit
- Definition Classes
- AnyRef
- Annotations
- @throws(classOf[java.lang.InterruptedException])
- final def wait(arg0: Long): Unit
- Definition Classes
- AnyRef
- Annotations
- @throws(classOf[java.lang.InterruptedException]) @native()
- final def wait(): Unit
- Definition Classes
- AnyRef
- Annotations
- @throws(classOf[java.lang.InterruptedException])
- 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 ofview
: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 theF[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 theSignal
/SignallingRef
. - Scenarios where conditions might change instantly, but thep
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 aSignal
to change, or waiting for the value of theSignal
of an orderedStream[IO, Int]
to be greater than a certain number.