lockfree_object_pool/
mutex_object_pool.rs

1use crate::{mutex_owned_reusable::MutexOwnedReusable, mutex_reusable::MutexReusable};
2use std::mem::ManuallyDrop;
3use std::sync::{Arc, Mutex};
4
5/// ObjectPool use a [`std::sync::Mutex`] over vector to secure multithread access to pull.
6/// # Example
7/// ```rust
8///  use lockfree_object_pool::MutexObjectPool;
9///
10///  let pool = MutexObjectPool::<u32>::new(
11///    ||  Default::default(),
12///    |v| {
13///      *v = 0;
14///    }
15///  );
16///  let mut item = pool.pull();
17///
18///  *item = 5;
19///  let work = *item * 5;
20/// ```
21pub struct MutexObjectPool<T> {
22    objects: Mutex<Vec<T>>,
23    reset: Box<dyn Fn(&mut T) + Send + Sync>,
24    init: Box<dyn Fn() -> T + Send + Sync>,
25}
26
27impl<T> MutexObjectPool<T> {
28    ///
29    /// Create an new [`MutexObjectPool`]
30    ///
31    /// # Arguments
32    /// * `init`  closure to create new item
33    /// * `reset` closure to reset item before reusage
34    ///
35    /// # Example
36    /// ```rust
37    ///  use lockfree_object_pool::MutexObjectPool;
38    ///
39    ///  let pool = MutexObjectPool::<u32>::new(
40    ///    ||  Default::default(),
41    ///    |v| {
42    ///      *v = 0;
43    ///    }
44    ///  );
45    /// ```
46    #[inline]
47    pub fn new<R, I>(init: I, reset: R) -> Self
48    where
49        R: Fn(&mut T) + Send + Sync + 'static,
50        I: Fn() -> T + Send + Sync + 'static,
51    {
52        Self {
53            objects: Mutex::new(Vec::new()),
54            reset: Box::new(reset),
55            init: Box::new(init),
56        }
57    }
58
59    ///
60    /// Create a new element. When the element is dropped, it returns in the pull.
61    ///
62    /// # Example
63    /// ```rust
64    ///  use lockfree_object_pool::MutexObjectPool;
65    ///
66    ///  let pool = MutexObjectPool::<u32>::new(
67    ///    ||  Default::default(),
68    ///    |v| {
69    ///      *v = 0;
70    ///    }
71    ///  );
72    ///  let mut item = pool.pull();
73    /// ```
74    #[inline]
75    pub fn pull(&self) -> MutexReusable<T> {
76        MutexReusable::new(
77            self,
78            ManuallyDrop::new(
79                self.objects
80                    .lock()
81                    .unwrap()
82                    .pop()
83                    .unwrap_or_else(&self.init),
84            ),
85        )
86    }
87
88    ///
89    /// Create a new element. When the element is dropped, it returns in the pull.
90    ///
91    /// # Example
92    /// ```rust
93    ///  use lockfree_object_pool::MutexObjectPool;
94    ///  use std::sync::Arc;
95    ///
96    ///  let pool = Arc::new(MutexObjectPool::<u32>::new(
97    ///    ||  Default::default(),
98    ///    |v| {
99    ///      *v = 0;
100    ///    }
101    ///  ));
102    ///  let mut item = pool.pull_owned();
103    /// ```
104    #[inline]
105    pub fn pull_owned(self: &Arc<Self>) -> MutexOwnedReusable<T> {
106        MutexOwnedReusable::new(
107            self.clone(),
108            ManuallyDrop::new(
109                self.objects
110                    .lock()
111                    .unwrap()
112                    .pop()
113                    .unwrap_or_else(&self.init),
114            ),
115        )
116    }
117
118    #[inline]
119    pub(crate) fn attach(&self, mut data: T) {
120        (self.reset)(&mut data);
121        self.objects.lock().unwrap().push(data);
122    }
123}