1use lazy_static::lazy_static;
39use lockfree::map::Map;
40use std::any::*;
41use std::sync::atomic::AtomicUsize;
42use std::sync::atomic::Ordering;
43use std::sync::{Arc, Mutex};
44
45struct Event {
46 id: usize,
47 pub(crate) callback: Arc<dyn Fn(&(dyn Any + Send + Sync)) + Send + Sync + 'static>,
48}
49
50pub struct EventSystem {
51 idx: AtomicUsize,
52 events: Map<TypeId, Mutex<Vec<Event>>>,
53}
54
55impl EventSystem {
56 pub fn singleton() -> &'static Self {
57 lazy_static! {
58 static ref SINGLETON: EventSystem = EventSystem {
59 idx: AtomicUsize::new(0),
60 events: Map::new()
61 };
62 };
63
64 &*SINGLETON
65 }
66
67 pub fn subscribe<T, F>(&self, callback: F) -> usize
69 where
70 T: 'static + Send + Sync,
71 F: Fn(&T) + Send + Sync + 'static,
72 {
73 let type_id = TypeId::of::<T>();
74 let list = if let Some(list) = self.events.get(&type_id) {
75 list
76 } else {
77 self.events.insert(type_id, Mutex::new(Vec::new()));
78 self.events.get(&type_id).unwrap()
79 };
80
81 let event = Event {
82 id: self.idx.fetch_add(1, Ordering::SeqCst),
83 callback: Arc::new(move |x: &(dyn Any + Send + Sync)| {
84 if let Some(val) = x.downcast_ref::<T>() {
85 callback(val);
86 } else {
87 println!(
88 "Wrong type for callback {:?}, expect {:?}",
89 type_name_of_val(x),
90 type_name::<T>()
91 );
92 }
93 }),
94 };
95 let id = event.id;
96 list.val().lock().unwrap().push(event);
97
98 id
99 }
100
101 pub fn unsubscribe<T>(&self, id: usize)
102 where
103 T: 'static + Send + Sync,
104 {
105 let type_id = TypeId::of::<T>();
106 if let Some(callbacks) = self.events.get(&type_id) {
107 callbacks.val().lock().unwrap().retain(|x| x.id != id);
108 }
109 }
110
111 pub fn publish<T: 'static + Send + Sync>(&self, arg: &T) {
112 let type_id = TypeId::of::<T>();
113 if let Some(callbacks) = self.events.get(&type_id) {
114 for event in callbacks.val().lock().unwrap().iter() {
115 (*event.callback)(arg);
116 }
117 } else {
118 println!("No callbacks for event {:?}", type_id);
119 }
120 }
121}