[−][src]Crate revent
Synchronous, recursive event system.
Introduction
An event system is a collection of objects that can receive and send signals.
In revent
we construct something called a hub
which contains Channels and/or Slots.
Each such signal container is just a list of Nodes (objects) interested in said signal.
Emitting an event is as simple as just running a function on the relevant channel.
revent
's types ensure that we do not need RefCell, and that we do not
accidentally mutably alias. Recursion can be achieved by suspending access to an object's &mut Self
.
Example
use revent::{Channel, Node, Slot, Suspend}; // Create signal traits. trait SignalA { fn signal_a(&mut self, hub: &MyHub); } trait SignalB { fn signal_b(&mut self, hub: &MyHub); } trait SignalC { fn signal_c(&mut self); } // Create a struct of channels and slots based on your signal traits. #[derive(Default)] struct MyHub { signal_a: Channel<dyn SignalA>, signal_b: Channel<dyn SignalB>, // A channel contains any number of nodes. signal_c: Slot<dyn SignalC>, // A slot contains only a single node. } // Create trait implementors. Note that `A` implements both `SignalA` and `SignalB`. struct A; struct B; struct C; impl SignalA for A { fn signal_a(&mut self, hub: &MyHub) { println!("A::signal_a: {:?}", self as *mut _); self.suspend(|| { // Suspend here in order to not panic. `signal_b` also contains this hub.signal_b.emit(|x| { // object, so we must ensure we relinquish access to `&mut`. x.signal_b(hub); }); }); } } impl SignalB for A { fn signal_b(&mut self, _: &MyHub) { println!("A::signal_b: {:?}", self as *mut _); } } impl SignalB for B { fn signal_b(&mut self, hub: &MyHub) { println!("B::signal_b: {:?}", self as *mut _); hub.signal_c.emit(|x| { // We can also emit without suspending self. If the channel or // slot we emit into contains the object from which we emit, then a panic will occur. x.signal_c(); }); } } impl SignalC for C { fn signal_c(&mut self) { println!("C::signal_c: {:?}", self as *mut _); } } // Instantiate `MyHub`. let mut hub = MyHub::default(); // Insert nodes into the hub. Nodes can be cloned and used on their own using the `emit` // method. let a = Node::new(A); hub.signal_a.insert(a.clone()); hub.signal_b.insert(a.clone()); hub.signal_b.insert(Node::new(B)); hub.signal_c.insert(Node::new(C)); // Run `a` and call `signal_a`. a.emit(|x| { x.signal_a(&hub); });
Output:
ⓘThis example is not tested
A::signal_a: 0x55efd14a8b70 A::signal_b: 0x55efd14a8b70 B::signal_b: 0x55efd14a8bf0 C::signal_c: 0x55efd14a8c50
Structs
Channel | Container for multiple Nodes. |
Node | Node containing arbitrary data. |
Slot | Container for a single optional Node. |
Traits
Suspend | Suspend an arbitrary |