Source

Trait Source 

Source
pub trait Source: Listen<Msg = ()> + Debug {
    type Value;

    // Required method
    fn get(&self) -> Self::Value;

    // Provided methods
    fn map<F, O>(self, function: F) -> Map<Self, F>
       where Self: Sized,
             F: Fn(Self::Value) -> O { ... }
    fn flatten(self) -> Flatten<Self>
       where Self: Sized,
             Self::Value: Source + Clone,
             Self::Listener: FromListener<OuterListener<Self>, ()>,
             <Self::Value as Listen>::Listener: FromListener<InnerListener<Self>, ()> { ... }
}
Expand description

Access to a value that might change and notifications when it does.

The change notifications given are of type (); they do not allow access to the new value. This is an unfortunate necessity to allow sources to deliver notifications after the value has changed (i.e. while not holding any lock) without also needing a clone of, or reference-counted pointer to, the value. (Listeners are, as always, encouraged not to do significant work, so, while a listener could try calling Source::get() immediately, this is not the intended architecture and is not guaranteed to work.)

If a Source is known to be in a state such that its value will never change again, then it should drop all of its current and future listeners. This may typically be accomplished through Notifier::close().

The type aliases sync::DynSource and unsync::DynSource are available for type-erased Sources with type-erased Listeners. If you want a value and don’t care about the type of the source it comes from, use them.

Additional traits sources may implement:

  • They should, but are not required to, implement Clone; if they do, all clones should have identical future behavior (values returned and messages sent).
  • They should implement fmt::Debug in a way which identifies the source rather than only its current value, if this is possible possible without printing memory addresses or other non-deterministic information.
  • They should implement fmt::Pointer to print an address or other information which uniquely identifies the source, if possible.

Required Associated Types§

Source

type Value

The type of value which can be obtained from this source.

This type should usually be clonable (because in any case, arbitrary copies of it can be obtained from Source::get()), but this is not required.

Required Methods§

Source

fn get(&self) -> Self::Value

Returns the most recent value.

§Panics

This method may, but is not required or expected to, panic if called from within one of this source’s listeners.

Provided Methods§

Source

fn map<F, O>(self, function: F) -> Map<Self, F>
where Self: Sized, F: Fn(Self::Value) -> O,

Takes a function and produces a Source which applies that function to the values of self.

§Caveats

Note that the function is called every time get() is called, and that change notifications will be forwarded regardless of whether the mapped output changed; there is no caching. Therefore, it is important that the function should be cheap, and if it is likely that the output value will change less often than the input value, then a different approach should be used.

§Example
use nosy::{unsync::Cell, Source as _};

let cell: Cell<i32> = Cell::new(1);
let source = cell.as_source().map(|value| value * 100);
assert_eq!(source.get(), 100);

cell.set(2);
assert_eq!(source.get(), 200);
Source

fn flatten(self) -> Flatten<Self>
where Self: Sized, Self::Value: Source + Clone, Self::Listener: FromListener<OuterListener<Self>, ()>, <Self::Value as Listen>::Listener: FromListener<InnerListener<Self>, ()>,

Converts a source of sources of some value into a source of that value.

§Caveats

The current implementation of Flatten uses an internal mutex. This mutex is locked while Flatten::get() is called, and while it is locked, <Self::Value as Clone>::clone() may be called. Therefore, if that clone() attempts to acquire a lock on something locked by the caller of Flatten::get(), a deadlock would occur. This should generally not be a risk because cloning most Sources should be purely a reference count update; you can enforce this by making sure that Self::Value is some variety of Arc, such as sync::DynSource.

§Example
use std::sync::Arc;
use nosy::{unsync::{Cell, DynSource}, Source as _};

let cell_inner_1: Cell<i32> = Cell::new(100);
let cell_inner_2: Cell<i32> = Cell::new(200);
let cell_outer: Cell<DynSource<i32>> = Cell::new(cell_inner_1.as_source());

let flattened_source: DynSource<i32> = Arc::new(cell_outer.as_source().flatten());
assert_eq!(flattened_source.get(), 100);

cell_inner_1.set(101);
assert_eq!(flattened_source.get(), 101);

cell_outer.set(cell_inner_2.as_source());
assert_eq!(flattened_source.get(), 200);

cell_inner_2.set(201);
assert_eq!(flattened_source.get(), 201);

Implementations on Foreign Types§

Source§

impl<T: ?Sized + Source> Source for &T

Source§

type Value = <T as Source>::Value

Source§

fn get(&self) -> Self::Value

Source§

impl<T: ?Sized + Source> Source for &mut T

Source§

type Value = <T as Source>::Value

Source§

fn get(&self) -> Self::Value

Source§

impl<T: ?Sized + Source> Source for Box<T>

Source§

type Value = <T as Source>::Value

Source§

fn get(&self) -> Self::Value

Source§

impl<T: ?Sized + Source> Source for Rc<T>

Source§

type Value = <T as Source>::Value

Source§

fn get(&self) -> Self::Value

Source§

impl<T: ?Sized + Source> Source for Arc<T>

Source§

type Value = <T as Source>::Value

Source§

fn get(&self) -> Self::Value

Implementors§

Source§

impl<S> Source for Flatten<S>
where S: Source<Value: Source + Clone>, S::Listener: FromListener<OuterListener<S>, ()>, <S::Value as Listen>::Listener: FromListener<InnerListener<S>, ()>,

Source§

type Value = <<S as Source>::Value as Source>::Value

Source§

impl<S, F, O> Source for Map<S, F>
where S: Source, F: Fn(S::Value) -> O,

Source§

type Value = O

Source§

impl<S, L> Source for CellSource<S, L>
where S: LoadStore<Value: Debug>, L: Listener<()>,

Source§

impl<T: Clone + Debug, L: Listener<()>> Source for Constant<T, L>

Source§

type Value = T