Struct maidsafe_utilities::event_sender::EventSender [] [src]

pub struct EventSender<Category, EventSubset> {
    // some fields omitted
}

This structure is coded to achieve event-subsetting. Receivers in Rust are blocking. One cannot listen to multiple receivers at the same time except by using try_recv which again is bad for the same reasons spin-lock based on some sleep is bad (wasting cycles, 50% efficient on an average etc.).

Consider a module that listens to signals from various other modules. Different modules want to talk to this one. So one solution is make a common event set and all senders (registered in all the interested modules) send events from the same set. This is bad for maintenance. Wrong modules might use events not expected to originate from them since it is just one huge event-set. Thus there is a need of event-subsetting and distribute this module-wise so we prevent modules from using wrong events, completely by design and code-mechanics.

We also don't want to spawn threads listening to different receivers (which could force shared ownership and is anyway silly otherwise too). This is what EventSender helps to salvage. A simple mechanism that does what a skip-list in linked list does. It brings forth a concept of an Umbrella event-category and an event subset. The creator of EventSender hard-codes the category for different observers. Each category only links to a particular event-subset and type information of this is put into EventSender too during its construction. Thus when distributed, the modules cannot cheat (do the wrong thing) by trying to fire an event they are not permitted to. Also a single thread listens to many receivers. All problems solved.

Examples

    #[derive(Debug, Clone)]
    enum EventCategory {
        Network,
        UserInterface,
    }

    #[derive(Debug)]
    enum NetworkEvent {
        Connected,
        Disconnected,
    }

    #[derive(Debug)]
    enum UiEvent {
        CreateDirectory,
        Terminate,
    }

    let (ui_event_tx, ui_event_rx) = std::sync::mpsc::channel();
    let (category_tx, category_rx) = std::sync::mpsc::channel();
    let (network_event_tx, network_event_rx) = std::sync::mpsc::channel();

    let ui_event_sender = maidsafe_utilities::event_sender
                                            ::EventSender::<EventCategory, UiEvent>
                                            ::new(ui_event_tx,
                                                  EventCategory::UserInterface,
                                                  category_tx.clone());

    let nw_event_sender = maidsafe_utilities::event_sender
                                            ::EventSender::<EventCategory, NetworkEvent>
                                            ::new(network_event_tx,
                                                  EventCategory::Network,
                                                  category_tx);

    let _joiner = maidsafe_utilities::thread::named("EventListenerThread", move || {
        for it in category_rx.iter() {
            match it {
                EventCategory::Network => {
                    if let Ok(network_event) = network_event_rx.try_recv() {
                        match network_event {
                            NetworkEvent::Connected    => { /* Do Something */ },
                            NetworkEvent::Disconnected => { /* Do Something */ },
                        }
                    }
                },
                EventCategory::UserInterface => {
                    if let Ok(ui_event) = ui_event_rx.try_recv() {
                        match ui_event {
                            UiEvent::Terminate       => break,
                            UiEvent::CreateDirectory => { /* Do Something */ },
                        }
                    }
                }
            }
        }
    });

    assert!(nw_event_sender.send(NetworkEvent::Connected).is_ok());
    assert!(ui_event_sender.send(UiEvent::CreateDirectory).is_ok());
    assert!(ui_event_sender.send(UiEvent::Terminate).is_ok());

Methods

impl<Category: Debug + Clone, EventSubset: Debug> EventSender<Category, EventSubset>
[src]

fn new(event_tx: Sender<EventSubset>, event_category: Category, event_category_tx: Sender<Category>) -> EventSender<Category, EventSubset>

Create a new instance of EventSender. Category type, category value and EventSubset type are baked into EventSender to disallow user code from misusing it.

fn send(&self, event: EventSubset) -> Result<()EventSenderError<Category, EventSubset>>

Fire an allowed event/signal to the observer.

Trait Implementations

impl<Category: Debug, EventSubset: Debug> Debug for EventSender<Category, EventSubset>
[src]

fn fmt(&self, __arg_0: &mut Formatter) -> Result

Formats the value using the given formatter.

impl<Category: Debug + Clone, EventSubset: Debug> Clone for EventSender<Category, EventSubset>
[src]

fn clone(&self) -> EventSender<Category, EventSubset>

Returns a copy of the value. Read more

fn clone_from(&mut self, source: &Self)
1.0.0

Performs copy-assignment from source. Read more