event_listener_primitives/
once.rs

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