[][src]Module revent::feed

Cycle-breaking poll-based backward channels.

A feed is a "feedback" from a "bottom-node" (a node that can not send any further signals as that would cause cycles) to any of its ascendants. The parents will have to pop elements from the feed whenever they want, which is typically done right after calling slot(s).

A feed consumer Node (called a Feedee) will have its own unique queue. This means that two nodes can use the same Feeder source, and consume objects at different rates without affecting each other. Items sent from the feeder are cloned to all feedees.

use revent::{Anchor, feed::{Feed, Feedee, Feeder}, Grapher, Manager, Node, Slot};
use std::{cell::RefCell, rc::Rc};

trait BasicSignal {
    fn basic(&mut self);
}

struct MyAnchor {
    basic_slot_1: Slot<dyn BasicSignal>,
    basic_slot_2: Slot<dyn BasicSignal>,
    feedback: Feed<usize>,
    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),
            feedback: Feed::new("feedback", &mng, 1),
            mng,
        }
    }
}
impl Anchor for MyAnchor {
    fn manager(&self) -> &Manager {
        &self.mng
    }
}

// ---

struct EmitterA {
    basic_slot_2: Slot<dyn BasicSignal>,
    feedback: Feedee<usize>,
}
struct A { emits: EmitterA }
impl Node<MyAnchor, EmitterA> for A {
    fn register_emits(hub: &MyAnchor) -> EmitterA {
        EmitterA {
            basic_slot_2: hub.basic_slot_2.clone(),
            feedback: hub.feedback.feedee(),
        }
    }

    fn register_listens(hub: &mut MyAnchor, item: Rc<RefCell<Self>>) {
        hub.basic_slot_1.register(item);
    }
    const NAME: &'static str = "A";
}

// Whenever we get a basic signal we pass it to the register_emits.
impl BasicSignal for A {
    fn basic(&mut self) {
        self.emits.basic_slot_2.emit(BasicSignal::basic);
        while let Some(item) = self.emits.feedback.pop() {
            println!("A: Got feedback: {}", item);
        }
    }
}

// ---

struct EmitterB {
    feedback: Feeder<usize>,
}
struct B { emits: EmitterB }
impl Node<MyAnchor, EmitterB> for B {
    fn register_emits(hub: &MyAnchor) -> EmitterB {
        EmitterB {
            feedback: hub.feedback.feeder(),
        }
    }

    fn register_listens(hub: &mut MyAnchor, item: Rc<RefCell<Self>>) {
        hub.basic_slot_2.register(item);
    }
    const NAME: &'static str = "B";
}

// Whenever we get a basic signal we pass it to the register_emits.
impl BasicSignal for B {
    fn basic(&mut self) {
        println!("Node B: Sending feedback to all subscribers");
        self.emits.feedback.feed(123);
    }
}

// ---

let mut hub = MyAnchor::new();
hub.subscribe(|emits| A { emits });
hub.subscribe(|emits| B { emits });

Grapher::new(hub.manager()).graph_to_file("target/feeds.png").unwrap();

Structs

Feed

Feedback mechanism to provide data to Nodes higher up in the revent DAG.

Feedee

Receiver part of Feed.

Feeder

Sender part of Feed.