1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
#[macro_use] extern crate crossbeam_channel; use crossbeam_channel::{unbounded, Receiver, Sender}; use std::{sync::Arc, thread}; pub trait EventListener<T> where T: Sync + Send, { fn dispatch(&self, _event: &T) {} } pub struct EventDispatcher<T> { tx: Sender<T>, rx: Receiver<T>, listeners: Vec<Arc<dyn EventListener<T> + Send + Sync>>, } pub struct EventDispatcherBuilder<T> { tx: Sender<T>, rx: Receiver<T>, listeners: Vec<Arc<dyn EventListener<T> + Send + Sync>>, } impl<T> EventDispatcherBuilder<T> where T: Sync + Send + Sized, { pub fn new() -> Self { let (tx, rx) = unbounded::<T>(); EventDispatcherBuilder { tx, rx, listeners: vec![], } } pub fn add_listener(mut self, listener: Arc<dyn EventListener<T> + Send + Sync>) -> Self { self.listeners.push(listener); self } pub fn build(self) -> EventDispatcher<T> { EventDispatcher { tx: self.tx.clone(), rx: self.rx.clone(), listeners: self.listeners, } } } impl<T> EventDispatcher<T> where T: Sized + Send + Sync + 'static, { pub fn emit(&self, event: T) { let _ = self.tx.send(event).expect("cannot send via channel"); } pub fn start(&self) { let rx_thread = self.rx.clone(); let listeners = self.listeners.clone(); let mut tried = 0; thread::spawn(move || loop { let rx_thread_c = rx_thread.clone(); let listeners_c = listeners.clone(); let h = thread::spawn(move || loop { select! { recv(rx_thread_c) -> msg => { for listener in listeners_c.iter() { if let Ok(event) = &msg { listener.dispatch(&event); } } } } }); let r = h.join(); match r { Ok(r) => eprintln!("event dispatcher thread ended! {:?}", r), Err(e) => { eprintln!("event dispatcher thread died! {:?}", e); } } eprintln!("Starting new event dispatcher thread again..."); tried = tried + 1; if tried >= 100 { eprintln!( "event dispatcher thread cannot be started after {} attempts!", tried ); break; } }); } pub fn get_channel(&self) -> &Sender<T> { &self.tx } }