[][src]Struct reducer::AsyncDispatcher

pub struct AsyncDispatcher<A, E>(_);

A handle that allows dispatching actions on a spawned Dispatcher (requires async).

AsyncDispatcher requires all actions to be of the same type A. An effective way to fulfill this requirement is to define actions as enum variants.

This type is a just lightweight handle that may be cloned and sent to other threads.

Example

use futures::executor::*;
use futures::prelude::*;
use futures::task::*;
use reducer::*;
use std::error::Error;
use std::io::{self, Write};
use std::pin::Pin;

// The state of your app.
#[derive(Clone)]
struct Calculator(i32);

// Actions the user can trigger.
enum Action {
    Add(i32),
    Sub(i32),
    Mul(i32),
    Div(i32),
}

impl Reducer<Action> for Calculator {
    fn reduce(&mut self, action: Action) {
        match action {
            Action::Add(x) => self.0 += x,
            Action::Sub(x) => self.0 -= x,
            Action::Mul(x) => self.0 *= x,
            Action::Div(x) => self.0 /= x,
        }
    }
}

// The user interface.
struct Console;

impl Reactor<Calculator> for Console {
    type Error = io::Error;
    fn react(&mut self, state: &Calculator) -> io::Result<()> {
        io::stdout().write_fmt(format_args!("{}\n", state.0))
    }
}

// Implementing Sink for Console, means it can asynchronously react to state changes.
impl Sink<Calculator> for Console {
    type Error = io::Error;

    fn poll_ready(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<()>> {
        Poll::Ready(Ok(()))
    }

    fn start_send(mut self: Pin<&mut Self>, state: Calculator) -> io::Result<()> {
        self.react(&state)
    }

    fn poll_flush(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<()>> {
        Poll::Ready(Ok(()))
    }

    fn poll_close(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<()>> {
        Poll::Ready(Ok(()))
    }
}

fn main() -> Result<(), Box<dyn Error>> {
    let store = Store::new(Calculator(0), Console);

    // Spin up a thread-pool.
    let mut executor = ThreadPool::new()?;

    // Process incoming actions on a background task.
    let (mut dispatcher, handle) = executor.spawn_dispatcher(store)?;

    dispatcher.dispatch(Action::Add(5))?; // eventually displays "5"
    dispatcher.dispatch(Action::Mul(3))?; // eventually displays "15"
    dispatcher.dispatch(Action::Sub(1))?; // eventually displays "14"
    dispatcher.dispatch(Action::Div(7))?; // eventually displays "2"

    // Dropping the AsyncDispatcher signals to the background task that
    // it can terminate once all pending actions have been processed.
    drop(dispatcher);

    // Wait for the background task to terminate.
    block_on(handle)?;

    Ok(())
}

Trait Implementations

impl<A: Clone, E: Clone> Clone for AsyncDispatcher<A, E>[src]

impl<A: Debug, E: Debug> Debug for AsyncDispatcher<A, E>[src]

impl<A, E> Dispatcher<A> for AsyncDispatcher<A, E>[src]

type Output = Result<(), AsyncDispatcherError>

Either confirmation that action has been dispatched or the reason why not.

fn dispatch(&mut self, action: A) -> Self::Output[src]

Sends an action to the associated spawned Dispatcher.

Once this call returns, the action may or may not have taken effect, but it's guaranteed to eventually do, unless the spawned Dispatcher terminates in between.

impl<A, E> Sink<A> for AsyncDispatcher<A, E>[src]

type Error = AsyncDispatcherError

The type of value produced by the sink when an error occurs.

impl<'pin, A, E> Unpin for AsyncDispatcher<A, E> where
    __AsyncDispatcher<'pin, A, E>: Unpin
[src]

Auto Trait Implementations

impl<A, E> !RefUnwindSafe for AsyncDispatcher<A, E>

impl<A, E> Send for AsyncDispatcher<A, E> where
    A: Send,
    E: Send

impl<A, E> Sync for AsyncDispatcher<A, E> where
    A: Send,
    E: Send

impl<A, E> !UnwindSafe for AsyncDispatcher<A, E>

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T, Item> SinkExt<Item> for T where
    T: Sink<Item> + ?Sized
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

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

The type returned in the event of a conversion error.