Expand description
Reactive channels for Cushy
Channels ensure that every message sent is delivered to a receiver. Dynamics contain values and can provide reactivity, but if a dynamic is updated more quickly than the change callbacks are executed, it is possible for change callbacks to not observe every value stored in the Dynamic. Channels allow building data flows that ensure every value written is observed.
Cushy supports two types of channels:
-
Multi-Producer, Single-Consumer (MPSC): One or more
Sender<T>
s send values to either aReceiver<T>
or a callback function.Created by:
unbounded()
bounded()
build()
.finish()
/build().bound(capacity).finish()
-
Broadcast: A
Broadcaster<T>
or aBroadcastChannel<T>
sends values to one or more callback functions. This type requiresT
to implementClone
as each callback receives its own clone of the value being broadcast.Broadcast channels ensure every callback associated is completed for each value received before receiving the next value.
Created by:
BroadcastChannel::unbounded()
BroadcastChannel::bounded()
build()
broadcasting().finish()
/build().bound(capacity).broadcasting().finish()
All channel types support being either unbounded or bounded. An unbounded channel dynamically allocates its queue and grows as needed. It can cause unexpected memory use or panics if the queues grow too large for the available system memory. Bounded channels allocate a buffer of a known capacity and can block on send or return errors when the queue is full.
One of the features provided by Cushy’s channels are the abilility to attach
callbacks to be executed when values are sent. Instead of needing to
manually spawn threads or async tasks, these callbacks are automatically
scheduled by Cushy, making channel reactivity feel similar to
Dynamic<T>
reactivity. However, channels
guarantee that the callbacks associated with them receive every value
written, while dynamics only guarantee that the latest written value will be
observed.
§Blocking callbacks
When a callback might block while waiting on another thread, a network task, or some other operation that may take a long time or require synchronization that could block (e.g., mutexes), it should be considered a blocking callback. Each blocking callback is executed in a way that ensures it cannot block any other operation while waiting for new values to be sent.
These callbacks can be configured using:
§Non-blocking callbacks
When a callback will never block for a significant amount of time or in a way that depends on other threads or callbacks or external resources, a non-blocking callback can be used. These callbacks are executed in a shared execution environment that minimizes resource consumption compared to what is required to execute blocking callbacks.
These callbacks can be configured using:
Receiver::on_receive_nonblocking
BroadcastChannel::on_receive_nonblocking
Builder::on_receive_nonblocking
§Async callbacks
If a callback needs to await
a future, an async callback can be used.
These callbacks are functions that take a value and return a future that can
be awaited to process the value. The future returned is awaited to
completion before the next value is received from the channel.
These callbacks can be configured using:
Modules§
- Builder types for Cushy
channel
s.
Structs§
- A future that broadcasts a value to a
BroadcastChannel<T>
. - A channel that broadcasts values received to one or more callbacks.
- Sends values to a
BroadcastChannel
. - A receiver for values sent by a
Sender
. - A future that sends a value to a channel.
- A sender of values to a channel.
Enums§
- An error trying to receive a value from a channel.
- An error occurred while trying to send a value to a channel.
Functions§
- Returns multi-producer, single-consumer channel that limits queued values to
capacity
items. - Returns a
Builder
for a Cushy channel. - Returns multi-producer, single-consumer channel with no limit to the number of values enqueued.