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}