Skip to main content

Module watch

Module watch 

Source
Expand description

A multi-producer, multi-consumer channel that retains only the last sent value.

channel returns a Sender and a Receiver around an initial value. Each Receiver tracks the last value seen by its own caller. The API is the established async watch-channel API; nothing here needs a runtime.

  • Receiver::borrow_and_update returns the current value and marks it seen. Receiver::borrow returns it without marking it seen.
  • Receiver::changed completes when a value the receiver has not seen is in the channel, and marks it seen. At creation the initial value is seen, and a receiver made by Sender::subscribe sees the value that was current at that moment as seen.
  • Receiver::has_changed is the synchronous check; it errors if and only if the channel is closed, while changed errors only when the channel is closed and the current value is seen.
  • Sender::is_closed and Sender::closed tell the producer that every Receiver is gone. The value is dropped when every sender and every receiver is gone.
use nuclei::sync::watch;

let (tx, mut rx) = watch::channel("hello");
assert_eq!(*rx.borrow_and_update(), "hello");
assert!(!rx.has_changed().unwrap());

tx.send("world").unwrap();
assert!(rx.has_changed().unwrap());
assert_eq!(*rx.borrow_and_update(), "world");

§The value lives in an Atom

Where a lock-based channel guards the value with a read-write lock, this one keeps it in an Atom. A send publishes a new allocation with one swap; a borrow is one protected load and never blocks a sender, and a sender never blocks a borrow. Two consequences follow, and both differ from the lock-based API:

  • The channel needs T: Send + Sync + 'static: values are shared by reference between threads and reclaimed later.
  • A Ref does not hold a lock but a reclamation guard. A value that was replaced stays allocated until every Ref that can see it is dropped, so keep a Ref short. It is !Send: it must be dropped on the thread that took it, and the compiler therefore refuses to hold one across an await in a task that may move threads.
  • The old value cannot be handed back by value while readers may still look at it, so Sender::send_replace returns a clone (T: Clone), and the two in-place modifiers, Sender::send_modify and Sender::send_if_modified, work on a clone too: they copy the value, let the closure change the copy and publish it with a compare-and-swap, retrying on a racing sender. Their closures are FnMut and may run more than once. A closure that panics, or that returns false from send_if_modified, publishes nothing, and the channel keeps the value it had.

§Progress

Modules§

error
Error types of the watch channel.

Structs§

Receiver
Receives values from the associated Senders.
Ref
A reference to the value inside the channel.
Sender
Sends values to the associated Receivers.

Functions§

channel
Creates a new watch channel around init, returning the send and receive handles.