1use parking_lot::Mutex;
79use std::iter::FromIterator;
80use std::mem::{forget, ManuallyDrop};
81use std::ops::{Deref, DerefMut};
82use std::sync::Arc;
83
84#[cfg(feature = "experimental")]
85pub mod experimental;
86
87pub type Stack<T> = Vec<T>;
88
89pub struct Pool<T> {
90 objects: Mutex<Stack<T>>,
91}
92
93impl<T> Pool<T> {
94 #[inline]
95 pub fn new<F>(cap: usize, init: F) -> Pool<T>
96 where
97 F: Fn() -> T,
98 {
99 Pool {
100 objects: Mutex::new((0..cap).into_iter().map(|_| init()).collect()),
101 }
102 }
103
104 #[inline]
105 pub fn from_vec(v: Vec<T>) -> Pool<T> {
106 Pool {
107 objects: Mutex::new(v),
108 }
109 }
110
111 #[inline]
112 pub fn len(&self) -> usize {
113 self.objects.lock().len()
114 }
115
116 #[inline]
117 pub fn is_empty(&self) -> bool {
118 self.objects.lock().is_empty()
119 }
120
121 #[inline]
122 pub fn try_pull(&self) -> Option<Reusable<T>> {
123 self.objects
124 .lock()
125 .pop()
126 .map(|data| Reusable::new(self, data))
127 }
128
129 #[inline]
130 pub fn pull<F: Fn() -> T>(&self, fallback: F) -> Reusable<T> {
131 self.try_pull()
132 .unwrap_or_else(|| Reusable::new(self, fallback()))
133 }
134
135 #[inline]
141 pub fn try_pull_owned(self: &Arc<Self>) -> Option<ReusableOwned<T>> {
142 self.objects
143 .lock()
144 .pop()
145 .map(|data| ReusableOwned::new(self.clone(), data))
146 }
147
148 #[inline]
153 pub fn pull_owned<F: Fn() -> T>(self: &Arc<Self>, fallback: F) -> ReusableOwned<T> {
154 self.try_pull_owned()
155 .unwrap_or_else(|| ReusableOwned::new(self.clone(), fallback()))
156 }
157
158 #[inline]
159 pub fn attach(&self, t: T) {
160 self.objects.lock().push(t)
161 }
162}
163
164impl<T> FromIterator<T> for Pool<T> {
165 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
166 Self {
167 objects: Mutex::new(iter.into_iter().collect()),
168 }
169 }
170}
171
172pub struct Reusable<'a, T> {
173 pool: &'a Pool<T>,
174 data: ManuallyDrop<T>,
175}
176
177impl<'a, T> Reusable<'a, T> {
178 #[inline]
179 pub fn new(pool: &'a Pool<T>, t: T) -> Self {
180 Self {
181 pool,
182 data: ManuallyDrop::new(t),
183 }
184 }
185
186 #[inline]
187 pub fn detach(mut self) -> (&'a Pool<T>, T) {
188 let ret = unsafe { (self.pool, self.take()) };
189 forget(self);
190 ret
191 }
192
193 unsafe fn take(&mut self) -> T {
194 ManuallyDrop::take(&mut self.data)
195 }
196}
197
198impl<'a, T> Deref for Reusable<'a, T> {
199 type Target = T;
200
201 #[inline]
202 fn deref(&self) -> &Self::Target {
203 &self.data
204 }
205}
206
207impl<'a, T> DerefMut for Reusable<'a, T> {
208 #[inline]
209 fn deref_mut(&mut self) -> &mut Self::Target {
210 &mut self.data
211 }
212}
213
214impl<'a, T> Drop for Reusable<'a, T> {
215 #[inline]
216 fn drop(&mut self) {
217 unsafe { self.pool.attach(self.take()) }
218 }
219}
220
221pub struct ReusableOwned<T> {
222 pool: ManuallyDrop<Arc<Pool<T>>>,
223 data: ManuallyDrop<T>,
224}
225
226impl<T> ReusableOwned<T> {
227 #[inline]
228 pub fn new(pool: Arc<Pool<T>>, t: T) -> Self {
229 Self {
230 pool: ManuallyDrop::new(pool),
231 data: ManuallyDrop::new(t),
232 }
233 }
234
235 #[inline]
236 pub fn detach(mut self) -> (Arc<Pool<T>>, T) {
237 let ret = unsafe { self.take() };
238 forget(self);
239 ret
240 }
241
242 unsafe fn take(&mut self) -> (Arc<Pool<T>>, T) {
243 (
244 ManuallyDrop::take(&mut self.pool),
245 ManuallyDrop::take(&mut self.data),
246 )
247 }
248}
249
250impl<T> Deref for ReusableOwned<T> {
251 type Target = T;
252
253 #[inline]
254 fn deref(&self) -> &Self::Target {
255 &self.data
256 }
257}
258
259impl<T> DerefMut for ReusableOwned<T> {
260 #[inline]
261 fn deref_mut(&mut self) -> &mut Self::Target {
262 &mut self.data
263 }
264}
265
266impl<T> Drop for ReusableOwned<T> {
267 #[inline]
268 fn drop(&mut self) {
269 let (pool, data) = unsafe { self.take() };
270 pool.attach(data);
271 }
272}
273
274#[cfg(test)]
275mod tests {
276 use crate::{Pool, Reusable};
277 use std::mem::drop;
278
279 #[test]
280 fn detach() {
281 let pool = Pool::new(1, || Vec::new());
282 let (pool, mut object) = pool.try_pull().unwrap().detach();
283 object.push(1);
284 Reusable::new(&pool, object);
285 assert_eq!(pool.try_pull().unwrap()[0], 1);
286 }
287
288 #[test]
289 fn detach_then_attach() {
290 let pool = Pool::new(1, || Vec::new());
291 let (pool, mut object) = pool.try_pull().unwrap().detach();
292 object.push(1);
293 pool.attach(object);
294 assert_eq!(pool.try_pull().unwrap()[0], 1);
295 }
296
297 #[test]
298 fn pull() {
299 let pool = Pool::<Vec<u8>>::new(1, || Vec::new());
300
301 let object1 = pool.try_pull();
302 let object2 = pool.try_pull();
303 let object3 = pool.pull(|| Vec::new());
304
305 assert!(object1.is_some());
306 assert!(object2.is_none());
307 drop(object1);
308 drop(object2);
309 drop(object3);
310 assert_eq!(pool.len(), 2);
311 }
312
313 #[test]
314 fn e2e() {
315 let pool = Pool::new(10, || Vec::new());
316 let mut objects = Vec::new();
317
318 for i in 0..10 {
319 let mut object = pool.try_pull().unwrap();
320 object.push(i);
321 objects.push(object);
322 }
323
324 assert!(pool.try_pull().is_none());
325 drop(objects);
326 assert!(pool.try_pull().is_some());
327
328 for i in (10..0).rev() {
329 let mut object = pool.objects.lock().pop().unwrap();
330 assert_eq!(object.pop(), Some(i));
331 }
332 }
333}