lockfree_object_pool/linear_object_pool.rs
1use crate::{
2 linear_owned_reusable::LinearOwnedReusable, linear_page::LinearPage,
3 linear_reusable::LinearReusable,
4};
5use std::sync::Arc;
6
7/// ObjectPool use a lockfree vector to secure multithread access to pull.
8///
9/// The lockfree vector is implemented as linked list.
10///
11/// # Example
12/// ```rust
13/// use lockfree_object_pool::LinearObjectPool;
14///
15/// let pool = LinearObjectPool::<u32>::new(
16/// || Default::default(),
17/// |v| {
18/// *v = 0;
19/// }
20/// );
21/// let mut item = pool.pull();
22///
23/// *item = 5;
24/// let work = *item * 5;
25/// ```
26pub struct LinearObjectPool<T> {
27 reset: Box<dyn Fn(&mut T) + Send + Sync>,
28 init: Box<dyn Fn() -> T + Send + Sync>,
29 head: LinearPage<T>,
30}
31
32impl<T> LinearObjectPool<T> {
33 ///
34 /// Create an new [`LinearObjectPool`]
35 ///
36 /// # Arguments
37 /// * `init` closure to create new item
38 /// * `reset` closure to reset item before reusage
39 ///
40 /// # Example
41 /// ```rust
42 /// use lockfree_object_pool::LinearObjectPool;
43 ///
44 /// let pool = LinearObjectPool::<u32>::new(
45 /// || Default::default(),
46 /// |v| {
47 /// *v = 0;
48 /// }
49 /// );
50 /// ```
51 #[inline]
52 pub fn new<R, I>(init: I, reset: R) -> Self
53 where
54 R: Fn(&mut T) + 'static + Send + Sync,
55 I: Fn() -> T + 'static + Clone + Send + Sync,
56 {
57 Self {
58 reset: Box::new(reset),
59 init: Box::new(init.clone()),
60 head: LinearPage::new(init),
61 }
62 }
63
64 ///
65 /// Create a new element. When the element is dropped, it returns in the pull.
66 ///
67 /// # Example
68 /// ```rust
69 /// use lockfree_object_pool::LinearObjectPool;
70 ///
71 /// let pool = LinearObjectPool::<u32>::new(
72 /// || Default::default(),
73 /// |v| {
74 /// *v = 0;
75 /// }
76 /// );
77 /// let mut item = pool.pull();
78 /// ```
79 #[inline]
80 pub fn pull(&self) -> LinearReusable<T> {
81 let (page, page_id) = self.head.alloc(&self.init);
82 unsafe { LinearReusable::new(self, page_id, page) }
83 }
84
85 ///
86 /// Create a new element. When the element is dropped, it returns in the pull.
87 ///
88 /// # Example
89 /// ```rust
90 /// use lockfree_object_pool::LinearObjectPool;
91 /// use std::sync::Arc;
92 ///
93 /// let pool = Arc::new(LinearObjectPool::<u32>::new(
94 /// || Default::default(),
95 /// |v| {
96 /// *v = 0;
97 /// }
98 /// ));
99 /// let mut item = pool.pull_owned();
100 /// ```
101 #[inline]
102 pub fn pull_owned(self: &Arc<Self>) -> LinearOwnedReusable<T> {
103 let (page, page_id) = self.head.alloc(&self.init);
104 unsafe { LinearOwnedReusable::new(self.clone(), page_id, page) }
105 }
106
107 #[inline]
108 pub(crate) fn get_reset_callback(&self) -> &dyn Fn(&mut T) {
109 &self.reset
110 }
111}