roopes_core/patterns/heap_pool/
refcell_box.rs

1//! Contains an implementation of [`HeapPool`]
2//! which allow client code to generate, use, and
3//! re-use heap-allocated objects efficiently.
4
5use super::HeapPool;
6use crate::prelude::*;
7use std::{
8    borrow::Borrow,
9    cell::RefCell,
10};
11
12/// Holds a list of allocated objects in a
13/// scalable pool.  Previously allocated
14/// objects can be checked back in after use, to
15/// prevent immediate deallocation.
16pub struct RefCellBox<T, F, W>
17where
18    F: Emitter<T>,
19    W: Handler<RefCell<T>>,
20{
21    unused_pool: Vec<Box<RefCell<T>>>,
22    new_gen: F,
23    grow_size: u8,
24    washer: W,
25}
26
27impl<T, F, W> RefCellBox<T, F, W>
28where
29    F: Emitter<T>,
30    W: Handler<RefCell<T>>,
31{
32    /// Creates a new [`RefCellBox`].
33    pub fn new(
34        unused_pool: Vec<Box<RefCell<T>>>,
35        new_gen: F,
36        grow_size: u8,
37        washer: W,
38    ) -> RefCellBox<T, F, W>
39    {
40        RefCellBox {
41            unused_pool,
42            new_gen,
43            grow_size,
44            washer,
45        }
46    }
47
48    /// Gets the current number of un-checked-out
49    /// items in the pool.  The
50    /// current "reserve" size.
51    pub fn unused_pool_size(&self) -> usize
52    {
53        self.unused_pool.len()
54    }
55
56    /// Grows the [`RefCellBox`] pool by the
57    /// previously specified quantity.
58    pub fn expand(&mut self)
59    {
60        (0..self.grow_size).for_each(|_| {
61            let pool_obj = Box::new(RefCell::new(self.new_gen.emit()));
62
63            self.unused_pool.push(pool_obj);
64        });
65    }
66}
67
68impl<T, F, W> HeapPool<Box<RefCell<T>>> for RefCellBox<T, F, W>
69where
70    F: Emitter<T>,
71    W: Handler<RefCell<T>>,
72{
73    fn check_out(&mut self) -> Box<RefCell<T>>
74    {
75        if self.unused_pool.is_empty() {
76            self.expand();
77        }
78
79        self.unused_pool.pop().expect("Unused pool is empty.")
80    }
81
82    fn check_in(
83        &mut self,
84        container: Box<RefCell<T>>,
85    )
86    {
87        self.washer.handle(container.borrow());
88        self.unused_pool.push(container);
89    }
90}