moirai_core/memory/pool.rs
1//! Capacity-bounded object pool parameterizing the crate's single
2//! slot-freelist implementation, [`crate::pool::LockFreeStack`].
3
4use crate::pool::LockFreeStack;
5
6/// Memory pool for reducing allocation overhead.
7///
8/// A capacity-bounded, lock-free object pool: [`Self::deallocate`] stores up to
9/// `max_size` objects for reuse and [`Self::allocate`] pops a stored object or
10/// falls back to `T::default()`. The freelist mechanics live in
11/// [`LockFreeStack`]; this type only adds the pool vocabulary
12/// (allocate/deallocate) over the stack's fixed slot capacity.
13pub struct MemoryPool<T> {
14 stack: LockFreeStack<T>,
15}
16
17impl<T> MemoryPool<T> {
18 /// Create a new memory pool retaining at most `max_size` objects.
19 #[must_use]
20 pub fn new(max_size: usize) -> Self {
21 Self {
22 stack: LockFreeStack::with_capacity(max_size),
23 }
24 }
25
26 /// Allocate an object from the pool or create new if pool is empty
27 pub fn allocate(&self) -> T
28 where
29 T: Default,
30 {
31 self.stack.pop().unwrap_or_default()
32 }
33
34 /// Return an object to the pool for reuse.
35 ///
36 /// When the pool already holds `max_size` objects the item is dropped;
37 /// this is the pool's documented retention cap, not an error condition.
38 pub fn deallocate(&self, item: T) {
39 if let Err(item) = self.stack.push(item) {
40 drop(item); // pool at capacity: intentional retention-cap drop
41 }
42 }
43
44 /// Get current pool size
45 pub fn size(&self) -> usize {
46 self.stack.len()
47 }
48}