[−][src]Crate revent
Synchronous event system.
What is an event system?
An event system is a set of slots which contain objects. A signal is emitted on a slot, which will call each object in the slot. Invoked objects can then send more signals to different slots.
Synchronous
Revent's events are synchronous, meaning that emitting an event will immediately process all handlers in a slot. Once the function call returns, it is guaranteed that all listeners have been called.
Basic Example
use revent::{Anchor, Manager, Node, Slot}; use std::{cell::RefCell, rc::Rc}; trait BasicSignal {} struct MyAnchor { basic_slot: Slot<dyn BasicSignal>, mng: Rc<RefCell<Manager>>, } impl MyAnchor { fn new() -> Self { let mng = Rc::new(RefCell::new(Manager::default())); Self { basic_slot: Slot::new("basic_slot", mng.clone()), mng, } } } impl Anchor for MyAnchor { fn manager(&self) -> &Rc<RefCell<Manager>> { &self.mng } } // --- struct MyNode; impl Node<MyAnchor, ()> for MyNode { fn register_emits(_: &MyAnchor) -> () { () } fn register_listens(hub: &mut MyAnchor, item: Rc<RefCell<Self>>) { hub.basic_slot.register(item); } const NAME: &'static str = "MyNode"; } impl BasicSignal for MyNode {} // --- let mut hub = MyAnchor::new(); let item = hub.subscribe(|_| MyNode); hub.basic_slot.emit(|x| { println!("Called for each subscriber"); }); hub.unsubscribe(&item);
Mutable cycles
Revent performs cycle detection in subscribe and ensures that no system exists in which we can create double mutable borrows.
Core Concepts
An event system based on revent has 3 core concepts:
- Slots
- Anchors
- Nodes
Slots
A slot is a container for item(s) that listen to that particular slot. Any signal emission on said slot will notify all items in that slot.
In this documentation slot
denotes both Slot and Single.
Anchor
An anchor contains all slots in a system. It also contains a Manager and implements Anchor. We register new Nodes to an anchor, and these nodes will themselves choose which slots to listen or emit to. Only anchors can be subscribed to.
Nodes
A node implements Node which contains the functions:
These specify the signals to emit and listen to. Any struct can be a node. Nodes are
constructed by first constructing the emitter structure as specified by register_emits
. This
structure is then provided to the Anchor::subscribe create
function.
When talking about the nodes subscribed (as per register_listens
) to a slot, the term subscriber
may be used.
Example with Emitter
use revent::{Anchor, Manager, Node, Slot}; use std::{cell::RefCell, rc::Rc}; // First let's crate a hub (Anchor) that contains two signals. trait BasicSignal { fn basic(&mut self); } struct MyAnchor { basic_slot_1: Slot<dyn BasicSignal>, basic_slot_2: Slot<dyn BasicSignal>, mng: Rc<RefCell<Manager>>, } impl MyAnchor { fn new() -> Self { let mng = Rc::new(RefCell::new(Manager::default())); Self { basic_slot_1: Slot::new("basic_slot_1", mng.clone()), basic_slot_2: Slot::new("basic_slot_2", mng.clone()), mng, } } } impl Anchor for MyAnchor { fn manager(&self) -> &Rc<RefCell<Manager>> { &self.mng } } // --- // Now we define our emitter structure, this one contains only `basic_slot_2`, which indicates // that we want to emit only to this slot for the subscribers using it as their register_emits. struct MyEmitter { basic_slot_2: Slot<dyn BasicSignal>, } // --- // Create a node that uses MyEmitter (emits on `basic_slot_2`), and listens on // `basic_slot_1`. struct MyNode { emits: MyEmitter } impl Node<MyAnchor, MyEmitter> for MyNode { // Indicate which slots we want to use. fn register_emits(hub: &MyAnchor) -> MyEmitter { MyEmitter { basic_slot_2: hub.basic_slot_2.clone(), } } fn register_listens(hub: &mut MyAnchor, item: Rc<RefCell<Self>>) { hub.basic_slot_1.register(item); } const NAME: &'static str = "MyNode"; } // Whenever we get a basic signal we pass it to the register_emits. impl BasicSignal for MyNode { fn basic(&mut self) { self.emits.basic_slot_2.emit(|_| println!("Hello world")); } } // --- let mut hub = MyAnchor::new(); // The type annotation is not needed, but shown here to show what to expect. let item = hub.subscribe(|emits: MyEmitter| MyNode { emits }); hub.basic_slot_1.emit(BasicSignal::basic); hub.unsubscribe(&item);
Structs
Grapher | Wrapper around a Manager that generates a graph. |
Manager | Inspects how various Nodes use slots. |
Single | Single slot containing |
Slot | List of Nodes to a signal |
Traits
Anchor | A collection of slots to which Nodes can subscribe. |
Node | Describes a subscriber that can subscribe to Anchor. |