Subscribing to events

How can subscribing to events be implemented in rust.

//pseudo code
GlobalState {
  fn subscribe(self, impl Fn())
}

impl ShortLivingObject {
  some_fn(self,global_state) {
    global_state.subscribe(|| self.do_something());
  }
}

Or it can be

trait Listener { fn on_event(); }
impl Listener for ShortLivingObject {
  fn on_event() {
    self.do_something();
  }
}

Anyways, that's not possible, because GlobalState should store references to ShortLivingObjects. The only idea I have is to wrap every object in Rc<RefCell>> and this will allow me to store weak references in GlobalState, but this feels so inconvenient.

Playground

struct Event {
    data: String,
}

type Handler = Box<dyn FnMut(&Event) -> Result<(), Box<dyn std::error::Error>>>;

fn handler2(_event: &Event) -> Result<(), Box<dyn std::error::Error>> {
    Err("failed to process event".into())
}

fn main() {
    let mut handlers: Vec<Handler> = vec![
        Box::new(|event: &Event| {
            println!("Received {}", event.data);
            Ok(())
        }),
        Box::new(handler2)
    ];
    
    let event = Event {
        data: "Some event".to_owned(),
    };
    
    for handler in &mut handlers {
        handler(&event).expect("event handler failed");
    }
}

I made some assumptions about what you might want from your event handlers. Depending on the context you may be able to get away with something simpler.

If your question is not actually how to implement event handlers/subscribing to events but how to share the event handlers throughout a program, consider using Rc<RefCell<Handlers>> or Arc<Mutex<Handlers>> in multi-threaded/async code.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.