Event Listener Paradigm Using Generics


#1

Hi! I’m trying to understand how to code events and listeners but I’m new :confused:

Expressed in C++ land, I would like to have a listener class and an event class.

Listeners are parameterized by K : Event, V. They have a function listen that listens to a message of type V. They should be able to listen to multiple K’s even when the V is the same:

listen(double d) #listens to K1 : Event
listen(double d) #listens to K2 : Event

The event class contains an iterable of listeners. An implementation of the event class has an iterable of listeners where the K is itself and the V can be specified depending on what I as an event communicate.

Here was my attempt at first:

trait Listener<K : Event, V> {
fn listen<K, V>(v : V);
}

struct Event {
l : Vec<Listener<Event, V>>,
}

impl Event {
fn activate_listeners(d : V) {
for n in l {
n.listen(d);
}
}
}

This won’t even compile :confused:

Thanks so so much for the help!
James


#2
use std::borrow::BorrowMut;
use std::cell::RefCell;
use std::mem;
use std::rc::Rc;

trait Event {
}

trait Listener<'a, E: Event + 'a> {
    fn handle_event(&mut self, event: &mut E);
}

struct PlainListener;

impl<'a> Listener<'a, PlainEvent<'a>> for PlainListener {
    fn handle_event(&mut self, _: &mut PlainEvent) {
        println!("PlainEvent handles event");
    }
}

impl PlainListener {
    fn new() -> Self {
        PlainListener
    }
}

struct PlainEvent<'a> {
    // One listener may listen to various events
    listeners: Vec<Rc<RefCell<Listener<'a, PlainEvent<'a>>>>>,
}

impl<'a> Event for PlainEvent<'a> {}

impl<'a> PlainEvent<'a> {
    fn new() -> Self {
        PlainEvent { listeners: Vec::new() }
    }

    fn activate(&mut self) {
        let mut listeners = Vec::new();
        mem::swap(&mut self.listeners, &mut listeners);

        for listener in &listeners {
            let listener: &RefCell<_> = listener;
            let mut listener = listener.borrow_mut();
            listener.handle_event(self); 
        }

        mem::swap(&mut self.listeners, &mut listeners);

        for listener in listeners {
            self.subscribe(listener);
        }
    } 

    fn subscribe(&mut self, listener: Rc<RefCell<Listener<'a, PlainEvent<'a>>>>) {
        self.listeners.push(listener); 
    }
}

fn main() {
    let mut event = PlainEvent::new();
    let first_listener = Rc::new(RefCell::new(PlainListener::new()));
    let second_listener = Rc::new(RefCell::new(PlainListener::new()));
    event.subscribe(first_listener);
    event.subscribe(second_listener);
    event.activate();
}

#4

This code has the interesting property that any subscriptions made while handling an event are silently ignored.


#5

Can you explain, why this happens? It’s not obvious to me at first glance.


#6

Because I swaps listeners at start of activation.


#7

I know about it, I will fix it.