[][src]Crate revent

Synchronous event system.

What is an event system

An event system is a set of signals connected to a bunch of objects. When a signal is emitted, the objects subscribing to said signal will have their handlers invoked to perform some useful processing.

Synchronous?

Revent is synchonous, meaning that calling emit will immediately call all subscribers. This also means that subscribers can return complex types with lifetimes referring to themselves.

Example

use revent::{shared, Topic};

// Create a trait for your event handler.
trait A {
    // Here is one "event". We call this on all handlers (implementors of A).
    fn a(&mut self);
}

// Create a struct implementing A.
struct X;

impl A for X {
    fn a(&mut self) {
        println!("Hello world");
    }
}

// Create a new topic channel.
let mut topic: Topic<dyn A> = Topic::new();

// Insert a new object of X.
topic.insert(shared(X));

// Iterate over all objects and call the event function.
topic.emit(|x| {
    x.a();
});

// Remove all subscribers to this topic.
topic.remove(|_| true);

Nested emitting

To allow for nested emitting we simply provide a &mut Topic<_> to an event handler. The next example shows this and its possible downside.

Mutable borrowing

It's possible to put a single object in two or more Topics. If one topic is able to emit into another topic then we may get a double-mutable borrow.

The following code panics because of 2 mutable borrows.

use revent::{shared, Topic};

trait A {
    fn a(&mut self, b: &mut Topic<dyn B>);
}

trait B {
    fn b(&mut self);
}

struct X;

impl A for X {
    fn a(&mut self, b: &mut Topic<dyn B>) {
        b.emit(|x| {
            x.b();
        });
    }
}

impl B for X {
    fn b(&mut self) {
    }
}

let mut a: Topic<dyn A> = Topic::new();
let mut b: Topic<dyn B> = Topic::new();

let x = shared(X);
a.insert(x.clone());
b.insert(x.clone());

a.emit(|x| {
    x.a(&mut b);
});

To avoid this, design all your event handler types to never emit into a handler they subscribe to. In the above case we have X subscribe to B while also emitting into a Topic<dyn B>. For larger systems it is highly advised to ensure all your event handlers never emit into a topic they also subscribe to.

Structs

Topic

A topic to which objects can subscribe.

Functions

shared

Wrapper for Rc::new(RefCell::new(_)).