ferroui_system/events/
handler_list.rs1use std::cell::{Cell, RefCell};
2use smallvec::SmallVec;
3use std::rc::Rc;
4use std::sync::atomic::{AtomicU64, Ordering};
5
6pub struct HandlerList<F: ?Sized> {
10 handlers: RefCell<Option<Rc<Handlers<F>>>>,
13 next_id: HandlerIds,
14}
15
16type Handlers<F> = SmallVec<[(u64, Rc<F>); 2]>;
19
20pub struct HandlerSnapshot<F: ?Sized>(Option<Rc<Handlers<F>>>);
23
24impl<F: ?Sized> Clone for HandlerSnapshot<F> {
25 fn clone(&self) -> Self {
26 Self(self.0.clone())
27 }
28}
29
30impl<F: ?Sized> std::ops::Deref for HandlerSnapshot<F> {
31 type Target = [(u64, Rc<F>)];
32
33 #[inline]
34 fn deref(&self) -> &[(u64, Rc<F>)] {
35 match &self.0 {
36 Some(handlers) => handlers,
37 None => &[],
38 }
39 }
40}
41
42enum HandlerIds {
44 Own(Cell<u64>),
45 Shared(Rc<Cell<u64>>),
48 Ordered,
52}
53
54static ORDERED_IDS: AtomicU64 = AtomicU64::new(1);
56
57impl HandlerIds {
58 fn next(&self) -> u64 {
59 let cell = match self {
60 Self::Own(cell) => cell,
61 Self::Shared(cell) => cell,
62 Self::Ordered => return ORDERED_IDS.fetch_add(1, Ordering::Relaxed),
63 };
64 let id = cell.get();
65 cell.set(id + 1);
66 id
67 }
68}
69
70impl<F: ?Sized> Default for HandlerList<F> {
71 fn default() -> Self {
72 Self::new()
73 }
74}
75
76impl<F: ?Sized> HandlerList<F> {
77 pub fn new() -> Self {
78 Self { handlers: RefCell::new(None), next_id: HandlerIds::Own(Cell::new(1)) }
79 }
80
81 pub fn with_shared_ids(ids: Rc<Cell<u64>>) -> Self {
84 Self { handlers: RefCell::new(None), next_id: HandlerIds::Shared(ids) }
85 }
86
87 pub fn with_ordered_ids() -> Self {
92 Self { handlers: RefCell::new(None), next_id: HandlerIds::Ordered }
93 }
94
95 #[inline]
96 pub fn is_empty(&self) -> bool {
97 self.handlers.borrow().as_ref().is_none_or(|handlers| handlers.is_empty())
98 }
99
100 pub fn len(&self) -> usize {
101 self.handlers.borrow().as_ref().map_or(0, |handlers| handlers.len())
102 }
103
104 pub fn add(&self, handler: Rc<F>) -> u64 {
106 let id = self.next_id.next();
107 let mut handlers = self.handlers.borrow_mut();
108 let handlers = handlers.get_or_insert_with(|| Rc::new(SmallVec::new()));
109 Rc::make_mut_or_clone(handlers).push((id, handler));
110 id
111 }
112
113 pub fn remove(&self, token: u64) -> bool {
115 let mut handlers = self.handlers.borrow_mut();
116 let Some(handlers) = handlers.as_mut() else {
117 return false;
118 };
119 match handlers.iter().position(|(id, _)| *id == token) {
120 Some(index) => {
121 Rc::make_mut_or_clone(handlers).remove(index);
122 true
123 }
124 None => false,
125 }
126 }
127
128 #[inline]
130 pub fn snapshot(&self) -> HandlerSnapshot<F> {
131 HandlerSnapshot(self.handlers.borrow().clone())
132 }
133}
134
135trait MakeMutOrClone<T> {
136 fn make_mut_or_clone(this: &mut Self) -> &mut T;
137}
138
139impl<F: ?Sized> MakeMutOrClone<Handlers<F>> for Rc<Handlers<F>> {
140 fn make_mut_or_clone(this: &mut Self) -> &mut Handlers<F> {
141 if Rc::get_mut(this).is_none() {
142 let copy: Handlers<F> = this.iter().map(|(id, f)| (*id, f.clone())).collect();
143 *this = Rc::new(copy);
144 }
145 Rc::get_mut(this).expect("uniquely owned after copy")
146 }
147}