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 #[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
22pub 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 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 pub fn call<A>(&self, applicator: A)
138 where
139 A: Fn(&F),
140 {
141 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 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 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 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 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 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 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}