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 #[derive(Debug)]
13 pub struct Private([()]);
14}
15
16struct Inner<F: Send + 'static> {
17 handlers: IntMap<usize, F>,
18 next_index: usize,
19}
20
21pub 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 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 pub fn call<A>(&self, applicator: A)
137 where
138 A: Fn(F),
139 {
140 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 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 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 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 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 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 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}