[−][src]Crate revent
Synchronous event system.
What is an event system?
An event system is a set of objects that can exchange messages with each other. The objects know nothing about each other, they just know their common contracts. This allows for code to be separated along logical boundaries, thus reducing complexity and increasing testability.
In revent each such object is called a Node, as it represents a node in a graph.
Each node decides for itself which channel
s it wants to listen to, as well as emit to. Using
this information we can construct a complete graph of node-to-node interactions. As we'll see,
this graph is a proper directed acyclic graph (DAG), and is important for Rust's mutable aliasing
rules.
Revent's events are synchronous, meaning that emitting
an event will immediately process all
handlers of that event. Once the function call returns, it is guaranteed that all listeners have
been called.
Extra
As a visual aid, the documentation tests contain a Grapher. To acquire the
images you'll need to run these code snippets and have graphviz
installed.
Mutable cycles
Revent performs cycle detection in subscribe and ensures that no system exists in which we can create double mutable borrows. After subscription, no cycle detection is performed, so the actual emitting and receiving part has the lowest possible overhead.
Core Concepts
A revent system has 3 core concepts:
- Channels
- Anchors
- Nodes
Channel
A channel is a container for item(s) that listen to that particular channel. Any signal emission on said channel will notify all items in that channel.
In this documentation channel
denotes Slot, Single, as well as feed.
Anchor
An anchor contains all channels 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 channels to listen or emit to. Only anchors can be subscribed to.
Nodes
A node implements Node which contains the functions:
These specify the channels 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 channel, the term subscriber
may be used.
Example
use revent::{Anchor, Grapher, 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: Manager, } impl MyAnchor { fn new() -> Self { let mng = Manager::new(); Self { basic_slot_1: Slot::new("basic_slot_1", &mng), basic_slot_2: Slot::new("basic_slot_2", &mng), mng, } } } impl Anchor for MyAnchor { fn manager(&self) -> &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); Grapher::new(hub.manager()).graph_to_file("target/example-with-emitter.png").unwrap();
Modules
feed | Cycle-breaking poll-based backward channels. |
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 | |
Node | Describes a subscriber that can subscribe to Anchor. |