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}