event_listener_primitives/
regular.rs

1use crate::HandlerId;
2use nohash_hasher::IntMap;
3use parking_lot::Mutex;
4use smallvec::SmallVec;
5use std::fmt;
6use std::marker::PhantomData;
7use std::sync::Arc;
8
9mod private {
10    /// Internal type unreachable externally
11    // This struct is intentionally made `!Sized` with `[()]` such that we have no overlap with
12    // `Sized` arguments in specialized versions of `call_simple` implementations below
13    #[derive(Debug)]
14    pub struct Private([()]);
15}
16
17struct Inner<F: Send + Sync + Clone + 'static> {
18    handlers: IntMap<usize, F>,
19    next_index: usize,
20}
21
22/// Data structure that holds `Fn()` event handlers
23pub struct Bag<
24    F: Send + Sync + Clone + 'static,
25    A1: ?Sized = private::Private,
26    A2: ?Sized = private::Private,
27    A3: ?Sized = private::Private,
28    A4: ?Sized = private::Private,
29    A5: ?Sized = private::Private,
30> {
31    inner: Arc<Mutex<Inner<F>>>,
32    a1: PhantomData<A1>,
33    a2: PhantomData<A2>,
34    a3: PhantomData<A3>,
35    a4: PhantomData<A4>,
36    a5: PhantomData<A5>,
37}
38
39impl<F, A1, A2, A3, A4, A5> fmt::Debug for Bag<F, A1, A2, A3, A4, A5>
40where
41    F: Send + Sync + Clone + 'static,
42    A1: ?Sized,
43    A2: ?Sized,
44    A3: ?Sized,
45    A4: ?Sized,
46    A5: ?Sized,
47{
48    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
49        f.debug_struct("Bag").finish()
50    }
51}
52
53impl<F, A1, A2, A3, A4, A5> Clone for Bag<F, A1, A2, A3, A4, A5>
54where
55    F: Send + Sync + Clone + 'static,
56    A1: ?Sized,
57    A2: ?Sized,
58    A3: ?Sized,
59    A4: ?Sized,
60    A5: ?Sized,
61{
62    fn clone(&self) -> Self {
63        Self {
64            inner: Arc::clone(&self.inner),
65            a1: PhantomData::default(),
66            a2: PhantomData::default(),
67            a3: PhantomData::default(),
68            a4: PhantomData::default(),
69            a5: PhantomData::default(),
70        }
71    }
72}
73
74impl<F, A1, A2, A3, A4, A5> Default for Bag<F, A1, A2, A3, A4, A5>
75where
76    F: Send + Sync + Clone + 'static,
77    A1: ?Sized,
78    A2: ?Sized,
79    A3: ?Sized,
80    A4: ?Sized,
81    A5: ?Sized,
82{
83    fn default() -> Self {
84        Self {
85            inner: Arc::new(Mutex::new(Inner {
86                handlers: IntMap::default(),
87                next_index: 0,
88            })),
89            a1: PhantomData::default(),
90            a2: PhantomData::default(),
91            a3: PhantomData::default(),
92            a4: PhantomData::default(),
93            a5: PhantomData::default(),
94        }
95    }
96}
97
98impl<F, A1, A2, A3, A4, A5> Bag<F, A1, A2, A3, A4, A5>
99where
100    F: Send + Sync + Clone + 'static,
101    A1: ?Sized,
102    A2: ?Sized,
103    A3: ?Sized,
104    A4: ?Sized,
105    A5: ?Sized,
106{
107    /// Add new event handler to a bag
108    pub fn add(&self, callback: F) -> HandlerId {
109        let index;
110
111        {
112            let mut inner = self.inner.lock();
113
114            index = loop {
115                let index = inner.next_index;
116                inner.next_index += 1;
117
118                if !inner.handlers.contains_key(&index) {
119                    inner.handlers.insert(index, callback);
120                    break index;
121                }
122            }
123        }
124
125        HandlerId::new({
126            let weak_inner = Arc::downgrade(&self.inner);
127
128            move || {
129                if let Some(inner) = weak_inner.upgrade() {
130                    inner.lock().handlers.remove(&index);
131                }
132            }
133        })
134    }
135
136    /// Call applicator with each handler and keep handlers in the bag
137    pub fn call<A>(&self, applicator: A)
138    where
139        A: Fn(&F),
140    {
141        // We collect handlers first in order to avoid holding lock while calling handlers
142        let handlers = self
143            .inner
144            .lock()
145            .handlers
146            .values()
147            .cloned()
148            .collect::<SmallVec<[F; 2]>>();
149        for handler in handlers.iter() {
150            applicator(handler);
151        }
152    }
153}
154
155impl<F: Fn() + Send + Sync + ?Sized + 'static> Bag<Arc<F>> {
156    /// Call each handler without arguments and keep handlers in the bag
157    pub fn call_simple(&self) {
158        self.call(|handler| handler())
159    }
160}
161
162impl<A1, F> Bag<Arc<F>, A1>
163where
164    A1: Sized,
165    F: Fn(&A1) + Send + Sync + ?Sized + 'static,
166{
167    /// Call each handler without arguments and keep handlers in the bag
168    pub fn call_simple(&self, a1: &A1) {
169        self.call(|handler| handler(a1))
170    }
171}
172
173impl<A1, A2, F> Bag<Arc<F>, A1, A2>
174where
175    A1: Sized,
176    A2: Sized,
177    F: Fn(&A1, &A2) + Send + Sync + ?Sized + 'static,
178{
179    /// Call each handler without arguments and keep handlers in the bag
180    pub fn call_simple(&self, a1: &A1, a2: &A2) {
181        self.call(|handler| handler(a1, a2))
182    }
183}
184
185impl<A1, A2, A3, F> Bag<Arc<F>, A1, A2, A3>
186where
187    A1: Sized,
188    A2: Sized,
189    A3: Sized,
190    F: Fn(&A1, &A2, &A3) + Send + Sync + ?Sized + 'static,
191{
192    /// Call each handler without arguments and keep handlers in the bag
193    pub fn call_simple(&self, a1: &A1, a2: &A2, a3: &A3) {
194        self.call(|handler| handler(a1, a2, a3))
195    }
196}
197
198impl<A1, A2, A3, A4, F> Bag<Arc<F>, A1, A2, A3, A4>
199where
200    A1: Sized,
201    A2: Sized,
202    A3: Sized,
203    A4: Sized,
204    F: Fn(&A1, &A2, &A3, &A4) + Send + Sync + ?Sized + 'static,
205{
206    /// Call each handler without arguments and keep handlers in the bag
207    pub fn call_simple(&self, a1: &A1, a2: &A2, a3: &A3, a4: &A4) {
208        self.call(|handler| handler(a1, a2, a3, a4))
209    }
210}
211
212impl<A1, A2, A3, A4, A5, F> Bag<Arc<F>, A1, A2, A3, A4, A5>
213where
214    A1: Sized,
215    A2: Sized,
216    A3: Sized,
217    A4: Sized,
218    A5: Sized,
219    F: Fn(&A1, &A2, &A3, &A4, &A5) + Send + Sync + ?Sized + 'static,
220{
221    /// Call each handler without arguments and keep handlers in the bag
222    pub fn call_simple(&self, a1: &A1, a2: &A2, a3: &A3, a4: &A4, a5: &A5) {
223        self.call(|handler| handler(a1, a2, a3, a4, a5))
224    }
225}