[][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. Event handlers can also emit further events synchronously.

Example

use revent::{hub, node, Subscriber};

// Here is a simple trait for a signal. All signals are traits.
trait A {
    fn function(&mut self);
}

// Create a new top-level hub, this contains all signals.
hub! {
    X {
        signal_1: A,
    }
}

// Make `MyHandler` subscribe to `channel`.
node! {
    X {
        signal_1: A,
    } => Node(MyHandler) {
    }
}

// Create the `MyHandler` struct.
struct MyHandler;
impl A for MyHandler {
    fn function(&mut self) {
        println!("Hello world");
    }
}

// Describe how to build an instance of `MyHandler`.
impl Subscriber for MyHandler {
    type Input = ();
    fn build(_node: Self::Node, _input: Self::Input) -> Self {
        Self
    }
}

// Create a new root hub instance.
let mut x = X::new();

// Add an instance of `MyHandler`.
let input = ();
x.subscribe::<MyHandler>(input);

// Emit an event on the `signal_1` channel.
x.signal_1().emit(|subscriber| {
    subscriber.function();
});

Nested emitting

To allow for nested emitting we specify which signals we wish to be able to emit to in our internal node.

use revent::{hub, node, Subscriber};

trait A {
    fn function_a(&mut self);
}

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

hub! {
    X {
        signal_1: A,
        signal_2: B,
    }
}

node! {
    X {
        signal_1: A,
    } => Node(MyHandler) {
        signal_2: B,
        // Node holds `signal_2` and is able to emit into this.
    }
}

struct MyHandler;
impl A for MyHandler {
    fn function_a(&mut self) { }
}

// Describe how to build an instance of `MyHandler`.
impl Subscriber for MyHandler {
    type Input = ();
    fn build(mut node: Self::Node, _input: Self::Input) -> Self {
        node.signal_2().emit(|subscriber| {
            subscriber.function_b();
        });
        Self
    }
}

Mutable borrowing

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

Revent avoids the possibility of mutable borrows at emit-time by performing a graph cycle search every time a type subscribes. The following code panics at the subscribe stage giving us a useful error message about how the cycle is formed.

The following prints [AToBHandler]a -> [BToAHandler]b -> a, meaning that AToBHandler listens to a and emits into b (which BToAHandler listens to), which then again emits into a, thus a cycle is formed that can cause a double mutable borrow.

use revent::{hub, node, Subscriber};

pub trait A {
    fn a(&mut self);
}

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

hub! {
    X {
        a: A,
        b: B,
    }
}

node! {
    X {
        a: A,
    } => AToB(AToBHandler) {
        b: B,
    }
}

struct AToBHandler {
    node: AToB,
}

impl A for AToBHandler {
    fn a(&mut self) {
        self.node.b().emit(|x| {
            x.b();
        });
    }
}

impl Subscriber for AToBHandler {
    type Input = ();
    fn build(node: Self::Node, _: Self::Input) -> Self {
        Self { node }
    }
}

node! {
    X {
        b: B,
    } => BToA(BToAHandler) {
        a: A,
    }
}

struct BToAHandler {
    node: BToA,
}

impl B for BToAHandler {
    fn b(&mut self) {
        self.node.a().emit(|x| {
            x.a();
        });
    }
}

impl Subscriber for BToAHandler {
    type Input = ();
    fn build(node: Self::Node, _: Self::Input) -> Self {
        Self { node }
    }
}

let mut x = X::new();
x.subscribe::<AToBHandler>(());
x.subscribe::<BToAHandler>(());

Macros

hub

Generate a top-level hub.

node

Generate an intermediate node in the signal chain.

Structs

Signal

Signal of interest, contains subscribers.

Traits

Subscriber

Describes how to build an object.