embassy-sync

Crates

git

Versions

default

Flavors

embassy_sync::watch

Struct Watch

Source
pub struct Watch<M: RawMutex, T: Clone, const N: usize> { /* private fields */ }
Expand description

The Watch is a single-slot signaling primitive that allows multiple receivers to concurrently await changes to the value. Unlike a Signal, Watch supports multiple receivers, and unlike a PubSubChannel, Watch immediately overwrites the previous value when a new one is sent, without waiting for all receivers to read the previous value.

This makes Watch particularly useful when a single task updates a value or “state”, and multiple other tasks need to be notified about changes to this value asynchronously. Receivers may “lose” stale values, as they are always provided with the latest value.

Typically, Watch instances are declared as static, and a Sender and Receiver (or DynSender and/or DynReceiver) are obtained where relevant. An AnonReceiver and DynAnonReceiver are also available, which do not increase the receiver count for the channel, and unwrapping is therefore not required, but it is not possible to .await the channel.


use futures_executor::block_on;
use embassy_sync::watch::Watch;
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;

let f = async {

static WATCH: Watch<CriticalSectionRawMutex, u8, 2> = Watch::new();

// Obtain receivers and sender
let mut rcv0 = WATCH.receiver().unwrap();
let mut rcv1 = WATCH.dyn_receiver().unwrap();
let mut snd = WATCH.sender();

// No more receivers, and no update
assert!(WATCH.receiver().is_none());
assert_eq!(rcv1.try_changed(), None);

snd.send(10);

// Receive the new value (async or try)
assert_eq!(rcv0.changed().await, 10);
assert_eq!(rcv1.try_changed(), Some(10));

// No update
assert_eq!(rcv0.try_changed(), None);
assert_eq!(rcv1.try_changed(), None);

snd.send(20);

// Using `get` marks the value as seen
assert_eq!(rcv1.get().await, 20);
assert_eq!(rcv1.try_changed(), None);

// But `get` also returns when unchanged
assert_eq!(rcv1.get().await, 20);
assert_eq!(rcv1.get().await, 20);

};
block_on(f);

Implementations§

Source§

impl<M: RawMutex, T: Clone, const N: usize> Watch<M, T, N>

Source

pub const fn new() -> Self

Create a new Watch channel.

Source

pub const fn new_with(data: T) -> Self

Create a new Watch channel with default data.

Source

pub fn sender(&self) -> Sender<'_, M, T, N>

Create a new Sender for the Watch.

Source

pub fn dyn_sender(&self) -> DynSender<'_, T>

Create a new DynSender for the Watch.

Source

pub fn receiver(&self) -> Option<Receiver<'_, M, T, N>>

Try to create a new Receiver for the Watch. If the maximum number of receivers has been reached, None is returned.

Source

pub fn dyn_receiver(&self) -> Option<DynReceiver<'_, T>>

Try to create a new DynReceiver for the Watch. If the maximum number of receivers has been reached, None is returned.

Source

pub fn anon_receiver(&self) -> AnonReceiver<'_, M, T, N>

Try to create a new AnonReceiver for the Watch.

Source

pub fn dyn_anon_receiver(&self) -> DynAnonReceiver<'_, T>

Try to create a new DynAnonReceiver for the Watch.

Source

pub fn get_msg_id(&self) -> u64

Returns the message ID of the latest message sent to the Watch.

This counter is monotonic, and is incremented every time a new message is sent.

Source

pub fn try_get(&self) -> Option<T>

Tries to get the value of the Watch.

Source

pub fn try_get_and<F>(&self, f: F) -> Option<T>
where F: Fn(&T) -> bool,

Tries to get the value of the Watch if it matches the predicate function f.

Trait Implementations§

Source§

impl<M: RawMutex, T: Clone, const N: usize> WatchBehavior<T> for Watch<M, T, N>

Source§

fn try_get(&self, id: Option<&mut u64>) -> Option<T>

Tries to get the value of the Watch, marking it as seen, if an id is given.
Source§

fn try_get_and( &self, id: Option<&mut u64>, f: &mut dyn Fn(&T) -> bool, ) -> Option<T>

Tries to get the value of the Watch if it matches the predicate function f, marking it as seen.
Source§

fn contains_value(&self) -> bool

Checks if the Watch is been initialized with a value.

Auto Trait Implementations§

§

impl<M, T, const N: usize> !Freeze for Watch<M, T, N>

§

impl<M, T, const N: usize> !RefUnwindSafe for Watch<M, T, N>

§

impl<M, T, const N: usize> Send for Watch<M, T, N>
where M: Send, T: Send,

§

impl<M, T, const N: usize> Sync for Watch<M, T, N>
where M: Sync, T: Send,

§

impl<M, T, const N: usize> Unpin for Watch<M, T, N>
where M: Unpin, T: Unpin,

§

impl<M, T, const N: usize> UnwindSafe for Watch<M, T, N>
where M: UnwindSafe, T: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.