1use std::cell::UnsafeCell;
10use std::mem::{ManuallyDrop, MaybeUninit};
11use std::ops::{Deref, DerefMut};
12use std::rc::{Rc, Weak};
13
14#[repr(C)]
19struct Inner<T> {
20 data: UnsafeCell<Vec<T>>,
22
23 reset: UnsafeCell<Box<dyn FnMut(&mut T)>>,
25
26 factory: UnsafeCell<MaybeUninit<Box<dyn FnMut() -> T>>>,
28}
29
30impl<T> Inner<T> {
31 fn new_bounded<R>(data: Vec<T>, reset: R) -> Self
33 where
34 R: FnMut(&mut T) + 'static,
35 {
36 Self {
37 data: UnsafeCell::new(data),
38 reset: UnsafeCell::new(Box::new(reset)),
39 factory: UnsafeCell::new(MaybeUninit::uninit()),
40 }
41 }
42
43 fn new_growable<F, R>(data: Vec<T>, factory: F, reset: R) -> Self
45 where
46 F: FnMut() -> T + 'static,
47 R: FnMut(&mut T) + 'static,
48 {
49 Self {
50 data: UnsafeCell::new(data),
51 reset: UnsafeCell::new(Box::new(reset)),
52 factory: UnsafeCell::new(MaybeUninit::new(Box::new(factory))),
53 }
54 }
55
56 #[inline]
58 fn try_pop(&self) -> Option<T> {
59 let data = unsafe { &mut *self.data.get() };
61 data.pop()
62 }
63
64 #[inline]
70 unsafe fn pop_or_create(&self) -> T {
71 unsafe {
72 let data = &mut *self.data.get();
73 match data.pop() {
74 Some(value) => value,
75 None => {
76 let factory = &mut *self.factory.get();
77 (factory.assume_init_mut())()
78 }
79 }
80 }
81 }
82
83 #[inline]
85 fn return_value(&self, value: &mut T) {
86 let reset = unsafe { &mut *self.reset.get() };
88 reset(value);
89 }
90
91 #[inline]
93 fn push(&self, value: T) {
94 let data = unsafe { &mut *self.data.get() };
96 data.push(value);
97 }
98
99 #[inline]
100 fn available(&self) -> usize {
101 unsafe { (*self.data.get()).len() }
103 }
104
105 #[inline]
106 fn is_empty(&self) -> bool {
107 self.available() == 0
108 }
109}
110
111pub struct BoundedPool<T> {
136 inner: Rc<Inner<T>>,
137}
138
139impl<T> BoundedPool<T> {
140 pub fn new<I, R>(capacity: usize, mut init: I, reset: R) -> Self
152 where
153 I: FnMut() -> T,
154 R: FnMut(&mut T) + 'static,
155 {
156 assert!(capacity > 0, "capacity must be non-zero");
157
158 let mut data = Vec::with_capacity(capacity);
159 for _ in 0..capacity {
160 data.push(init());
161 }
162
163 Self {
164 inner: Rc::new(Inner::new_bounded(data, reset)),
165 }
166 }
167
168 #[inline]
172 pub fn try_acquire(&self) -> Option<Pooled<T>> {
173 self.inner.try_pop().map(|value| Pooled {
174 value: ManuallyDrop::new(value),
175 inner: Rc::downgrade(&self.inner),
176 })
177 }
178
179 #[inline]
181 pub fn available(&self) -> usize {
182 self.inner.available()
183 }
184
185 #[inline]
187 pub fn is_empty(&self) -> bool {
188 self.inner.is_empty()
189 }
190}
191
192pub struct Pool<T> {
219 inner: Rc<Inner<T>>,
220}
221
222impl<T> Pool<T> {
223 pub fn new<F, R>(factory: F, reset: R) -> Self
230 where
231 F: FnMut() -> T + 'static,
232 R: FnMut(&mut T) + 'static,
233 {
234 Self {
235 inner: Rc::new(Inner::new_growable(Vec::new(), factory, reset)),
236 }
237 }
238
239 pub fn with_capacity<F, R>(capacity: usize, mut factory: F, reset: R) -> Self
241 where
242 F: FnMut() -> T + 'static,
243 R: FnMut(&mut T) + 'static,
244 {
245 let mut data = Vec::with_capacity(capacity);
246 for _ in 0..capacity {
247 data.push(factory());
248 }
249
250 Self {
251 inner: Rc::new(Inner::new_growable(data, factory, reset)),
252 }
253 }
254
255 #[inline]
259 pub fn acquire(&self) -> Pooled<T> {
260 let value = unsafe { self.inner.pop_or_create() };
262 Pooled {
263 value: ManuallyDrop::new(value),
264 inner: Rc::downgrade(&self.inner),
265 }
266 }
267
268 #[inline]
272 pub fn try_acquire(&self) -> Option<Pooled<T>> {
273 self.inner.try_pop().map(|value| Pooled {
274 value: ManuallyDrop::new(value),
275 inner: Rc::downgrade(&self.inner),
276 })
277 }
278
279 #[inline]
281 pub fn available(&self) -> usize {
282 self.inner.available()
283 }
284}
285
286impl<T> Drop for Pool<T> {
287 fn drop(&mut self) {
288 unsafe {
291 let factory = &mut *self.inner.factory.get();
292 factory.assume_init_drop();
293 }
294 }
295}
296
297pub struct Pooled<T> {
306 value: ManuallyDrop<T>,
307 inner: Weak<Inner<T>>,
308}
309
310impl<T> Deref for Pooled<T> {
311 type Target = T;
312
313 #[inline]
314 fn deref(&self) -> &T {
315 &self.value
316 }
317}
318
319impl<T> DerefMut for Pooled<T> {
320 #[inline]
321 fn deref_mut(&mut self) -> &mut T {
322 &mut self.value
323 }
324}
325
326impl<T> Drop for Pooled<T> {
327 fn drop(&mut self) {
328 if let Some(inner) = self.inner.upgrade() {
329 inner.return_value(&mut self.value);
331 let value = unsafe { ManuallyDrop::take(&mut self.value) };
333 inner.push(value);
334 } else {
335 unsafe { ManuallyDrop::drop(&mut self.value) };
338 }
339 }
340}
341
342#[cfg(test)]
347mod tests {
348 use super::*;
349 use std::cell::Cell;
350 use std::rc::Rc as StdRc;
351
352 #[test]
353 fn bounded_pool_basic() {
354 let pool = BoundedPool::new(3, || Vec::<u8>::with_capacity(16), |v| v.clear());
355
356 assert_eq!(pool.available(), 3);
357
358 let mut a = pool.try_acquire().unwrap();
359 assert_eq!(pool.available(), 2);
360
361 a.extend_from_slice(b"hello");
362 assert_eq!(&*a, b"hello");
363
364 let _b = pool.try_acquire().unwrap();
365 let _c = pool.try_acquire().unwrap();
366
367 assert_eq!(pool.available(), 0);
368
369 assert!(pool.try_acquire().is_none());
371
372 drop(a);
373 assert_eq!(pool.available(), 1);
374
375 let d = pool.try_acquire().unwrap();
377 assert!(d.is_empty()); }
379
380 #[test]
381 fn bounded_pool_reset_called() {
382 let reset_count = StdRc::new(Cell::new(0));
383 let reset_count_clone = reset_count.clone();
384
385 let pool = BoundedPool::new(
386 2,
387 || 0u32,
388 move |_| {
389 reset_count_clone.set(reset_count_clone.get() + 1);
390 },
391 );
392
393 let a = pool.try_acquire().unwrap();
394 assert_eq!(reset_count.get(), 0);
395
396 drop(a);
397 assert_eq!(reset_count.get(), 1);
398
399 let b = pool.try_acquire().unwrap();
400 let c = pool.try_acquire().unwrap();
401 drop(b);
402 drop(c);
403 assert_eq!(reset_count.get(), 3);
404 }
405
406 #[test]
407 fn bounded_pool_outlives_guard() {
408 let guard;
409 {
410 let pool = BoundedPool::new(1, || String::from("test"), |s| s.clear());
411 guard = pool.try_acquire().unwrap();
412 }
413 assert_eq!(&*guard, "test");
415 drop(guard);
417 }
418
419 #[test]
420 fn growable_pool_basic() {
421 let pool = Pool::new(|| Vec::<u8>::with_capacity(16), |v| v.clear());
422
423 assert_eq!(pool.available(), 0);
424
425 let mut a = pool.acquire();
427 a.extend_from_slice(b"hello");
428
429 drop(a);
430 assert_eq!(pool.available(), 1);
431
432 let b = pool.acquire();
434 assert!(b.is_empty()); assert_eq!(pool.available(), 0);
436 }
437
438 #[test]
439 fn growable_pool_try_acquire() {
440 let pool = Pool::new(|| 42u32, |_| {});
441
442 assert!(pool.try_acquire().is_none());
444
445 let a = pool.acquire();
447 drop(a);
448
449 let b = pool.try_acquire().unwrap();
451 assert_eq!(*b, 42);
452 }
453
454 #[test]
455 fn growable_pool_with_capacity() {
456 let pool = Pool::with_capacity(5, || String::new(), |s| s.clear());
457
458 assert_eq!(pool.available(), 5);
459
460 let _a = pool.try_acquire().unwrap();
461 let _b = pool.try_acquire().unwrap();
462 assert_eq!(pool.available(), 3);
463 }
464
465 #[test]
466 fn growable_pool_outlives_guard() {
467 let guard;
468 {
469 let pool = Pool::new(|| String::from("test"), |s| s.clear());
470 guard = pool.acquire();
471 }
472 assert_eq!(&*guard, "test");
474 drop(guard);
475 }
476
477 #[test]
478 #[should_panic(expected = "capacity must be non-zero")]
479 fn bounded_pool_zero_capacity_panics() {
480 let _ = BoundedPool::new(0, || (), |_| {});
481 }
482}