easy_pool/
lib.rs

1#![cfg_attr(docsrs, feature(doc_cfg))]
2#![cfg_attr(docsrs, allow(unused_attributes))]
3#![doc = include_str!("../README.md")]
4
5use std::{
6    mem::ManuallyDrop,
7    ops::{Deref, DerefMut},
8    ptr,
9    sync::Arc,
10};
11
12pub use easy_pool_proc_macro::{EasyPoolArayQueue, EasyPoolMutex, EasyPoolSegQueue};
13pub use once_cell::sync::Lazy;
14pub use pool_array_queue::PoolArrayQueue;
15pub use pool_mutex::PoolMutex;
16pub use pool_seg_queue::PoolSegQueue;
17
18mod pool_array_queue;
19mod pool_mutex;
20mod pool_seg_queue;
21
22pub trait Clear {
23    fn clear(&mut self);
24}
25
26#[derive(Debug)]
27enum PoolType<T: Clear> {
28    Mutex(Arc<PoolMutex<T>>),
29    SegQueue(Arc<PoolSegQueue<T>>),
30    ArrayQueue(Arc<PoolArrayQueue<T>>),
31}
32
33#[derive(Debug)]
34pub struct PoolObjectContainer<T: Clear> {
35    ref_pool: PoolType<T>,
36    inner: ManuallyDrop<T>,
37}
38
39impl<T: Clear> PoolObjectContainer<T> {
40    fn new(val: T, ref_pool: PoolType<T>) -> Self {
41        Self {
42            inner: ManuallyDrop::new(val),
43            ref_pool,
44        }
45    }
46}
47
48impl<T: Clear> DerefMut for PoolObjectContainer<T> {
49    fn deref_mut(&mut self) -> &mut Self::Target {
50        &mut self.inner
51    }
52}
53
54impl<T: Clear> Deref for PoolObjectContainer<T> {
55    type Target = T;
56
57    fn deref(&self) -> &Self::Target {
58        &self.inner
59    }
60}
61
62impl<T: Clear> Drop for PoolObjectContainer<T> {
63    fn drop(&mut self) {
64        let val = unsafe { ptr::read(&self.inner) };
65        let mut val = ManuallyDrop::into_inner(val);
66
67        match self.ref_pool {
68            PoolType::Mutex(ref pool) => {
69                let mut lock = pool.values.lock();
70
71                if lock.len() >= pool.max_size {
72                    drop(val);
73                } else {
74                    val.clear();
75                    lock.push(val);
76                }
77                drop(lock);
78            }
79            PoolType::SegQueue(ref pool) => {
80                if pool.values.len() >= pool.max_size {
81                    drop(val);
82                } else {
83                    val.clear();
84                    pool.values.push(val);
85                }
86            }
87            PoolType::ArrayQueue(ref pool) => {
88                if pool.values.len() >= pool.max_size {
89                    drop(val);
90                } else {
91                    val.clear();
92                    if let Err(val) = pool.values.push(val) {
93                        drop(val);
94                    }
95                }
96            }
97        }
98    }
99}
100
101#[cfg(test)]
102mod tests {
103    use super::*;
104
105    #[test]
106    fn test_clear() {
107        let pool = Arc::new(PoolMutex::new());
108        let vec = pool.create_with(|| vec![10]);
109        drop(vec);
110        assert_eq!(pool.len(), 1);
111        let vec = pool.create();
112        assert!(vec.capacity() == 1 && vec.is_empty());
113
114        let pool = Arc::new(PoolSegQueue::new(1024));
115        let vec = pool.create_with(|| vec![10]);
116        drop(vec);
117        assert_eq!(pool.len(), 1);
118        let vec = pool.create();
119        assert!(vec.capacity() == 1 && vec.is_empty());
120
121        let pool = Arc::new(PoolArrayQueue::new(1024));
122        let vec = pool.create_with(|| vec![10]);
123        drop(vec);
124        assert_eq!(pool.len(), 1);
125        let vec = pool.create();
126        assert!(vec.capacity() == 1 && vec.is_empty());
127    }
128}