[−][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.
Example
use revent::{Anchor, Manager, Named, Null, Slot, Subscriber}; use std::{cell::RefCell, rc::Rc}; trait BasicSignal {} struct Hub { basic_slot: Slot<dyn BasicSignal>, mng: Rc<RefCell<Manager>>, } impl Hub { fn new() -> Self { let mng = Rc::new(RefCell::new(Manager::default())); Self { basic_slot: Slot::new("basic_slot", mng.clone()), mng, } } } impl Anchor for Hub { fn manager(&self) -> &Rc<RefCell<Manager>> { &self.mng } } // --- struct MySubscriber; impl Subscriber<Hub> for MySubscriber { type Emitter = Null; fn register(hub: &mut Hub, item: Rc<RefCell<Self>>) { hub.basic_slot.register(item); } } impl Named for MySubscriber { const NAME: &'static str = "MySubscriber"; } impl BasicSignal for MySubscriber {} // --- let mut hub = Hub::new(); let item = hub.subscribe(|_| MySubscriber); 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:
- Anchors
- Emitters
- Subscribers
Anchor
An anchor contains all event Slots and Singles in the system. It also contains a Manager and implements Anchor. We register new Subscribers to an anchor, and the subscribers will themselves choose which slots/singles to listen or emit to. Only anchors can be subscribed to.
Subscriber
Subscribers are classes that implement Subscriber<A: Anchor>
. They specify their interest in
signals to listen to by fn register
. They specify their singles/slots to emit to via type Emitter
.
Emitter
Each subscriber has an associated Emitter. An emitter contains a list of singles and slots
based on the Anchor
of its subscriber. Emitters simply implement From for &Anchor
which
clones singles and slots from a particular anchor.
Example with Emitter
use revent::{Anchor, Manager, Named, Null, Slot, Subscriber}; use std::{cell::RefCell, rc::Rc}; // First let's crate a hub (Anchor) that contains two signals. trait BasicSignal { fn basic(&mut self); } struct Hub { basic_slot_1: Slot<dyn BasicSignal>, basic_slot_2: Slot<dyn BasicSignal>, mng: Rc<RefCell<Manager>>, } impl Hub { 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 Hub { 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 emitter. struct MyEmitter { basic_slot_2: Slot<dyn BasicSignal>, } impl From<&Hub> for MyEmitter { fn from(item: &Hub) -> Self { Self { basic_slot_2: item.basic_slot_2.clone(), } } } // --- // Create a subscriber that uses MyEmitter (emits on `basic_slot_2`), and listens on // `basic_slot_1`. struct MySubscriber { emitter: MyEmitter } impl Subscriber<Hub> for MySubscriber { // Indicate which emitter we want to use. type Emitter = MyEmitter; fn register(hub: &mut Hub, item: Rc<RefCell<Self>>) { hub.basic_slot_1.register(item); } } impl Named for MySubscriber { const NAME: &'static str = "MySubscriber"; } // Whenever we get a basic signal we pass it to the emitter. impl BasicSignal for MySubscriber { fn basic(&mut self) { self.emitter.basic_slot_2.emit(|_| println!("Hello world")); } } // --- let mut hub = Hub::new(); let item = hub.subscribe(|emitter| MySubscriber { emitter }); hub.basic_slot_1.emit(BasicSignal::basic); hub.unsubscribe(&item);
Structs
Grapher | Wrapper around a Manager that generates a graph. |
Manager | Inspects how various Subscribers use Slots. |
Null | Null |
Single | Single Subscriber to a signal |
Slot | List of Subscribers to a signal |
Traits
Anchor | A collection of Slots and Singles to which Subscribers can subscribe. |
Named | Attach a name to a type. |
Subscriber | Describes a subscriber that can subscribe to Anchor. |