use std::collections::HashMap;
use std::sync::{Arc, Mutex};
use std::task::Waker;
pub struct EventEmitter {
listeners: Arc<Mutex<HashMap<String, Vec<Arc<Mutex<Listener>>>>>>,
}
pub(crate) struct Listener {
callback: Box<dyn Fn(&crate::interact::events::event::Event) + Send + 'static>,
waker: Option<Waker>,
}
impl EventEmitter {
pub fn new() -> Self {
Self {
listeners: Arc::new(Mutex::new(HashMap::new())),
}
}
pub fn emit(&self, event_type: &str, event: crate::interact::events::event::Event) -> bool {
let listeners = {
let guard = self.listeners.lock().unwrap();
guard.get(event_type).cloned().unwrap_or_default()
};
if listeners.is_empty() {
return false;
}
for listener in listeners {
let listener_guard = listener.lock().unwrap();
(listener_guard.callback)(&event);
if event.did_stop_immediate_propagation() {
break;
}
if let Some(ref waker) = listener_guard.waker {
waker.wake_by_ref();
}
}
true
}
pub(crate) fn on(
&self,
event_type: &str,
callback: Box<dyn Fn(&crate::interact::events::event::Event) + Send + 'static>,
) -> Arc<Mutex<Listener>> {
let listener = Arc::new(Mutex::new(Listener {
callback,
waker: None,
}));
let mut guard = self.listeners.lock().unwrap();
guard
.entry(event_type.to_string())
.or_default()
.push(listener.clone());
listener
}
pub fn once(
&self,
event_type: &str,
callback: Box<dyn Fn(&crate::interact::events::event::Event) + Send + 'static>,
) {
let emitter = self.clone();
let event_type_owned = event_type.to_string();
let callback = Box::new(move |event: &crate::interact::events::event::Event| {
callback(event);
emitter.remove_all_listeners(&event_type_owned);
});
let _ = self.on(event_type, callback);
}
pub fn remove_all_listeners(&self, event_type: &str) {
let mut guard = self.listeners.lock().unwrap();
guard.remove(event_type);
}
pub(crate) fn remove_listener(&self, listener: &Arc<Mutex<Listener>>) {
let mut guard = self.listeners.lock().unwrap();
for listeners in guard.values_mut() {
listeners.retain(|l| !Arc::ptr_eq(l, listener));
}
}
pub fn listener_count(&self, event_type: &str) -> usize {
let guard = self.listeners.lock().unwrap();
guard.get(event_type).map(|l| l.len()).unwrap_or(0)
}
pub fn clear(&self) {
let mut guard = self.listeners.lock().unwrap();
guard.clear();
}
}
impl Default for EventEmitter {
fn default() -> Self {
Self::new()
}
}
impl Clone for EventEmitter {
fn clone(&self) -> Self {
Self {
listeners: self.listeners.clone(),
}
}
}