orx_selfref_col/memory/
on_threshold.rs

1use super::{policy::MemoryPolicy, reclaimer::MemoryReclaimer};
2use crate::{CoreCol, Node, NodePtr, SelfRefCol, Variant};
3use core::marker::PhantomData;
4use orx_pinned_vec::PinnedVec;
5
6/// Memory reclaim policy which triggers the reclaim operation whenever the node utilization
7/// falls below a certain threshold.
8///
9/// Specifically, memory of closed nodes will be reclaimed whenever the ratio of closed nodes to all nodes exceeds one over `2^D`.
10/// * when `D = 0`: memory will be reclaimed when utilization is below 0.00% (equivalent to never).
11/// * when `D = 1`: memory will be reclaimed when utilization is below 50.00%.
12/// * when `D = 2`: memory will be reclaimed when utilization is below 75.00%.
13/// * when `D = 3`: memory will be reclaimed when utilization is below 87.50%.
14/// * when `D = 4`: memory will be reclaimed when utilization is below 93.75%.
15pub struct MemoryReclaimOnThreshold<const D: usize, V: Variant, R: MemoryReclaimer<V>> {
16    phantom: PhantomData<(V, R)>,
17}
18
19impl<const D: usize, V: Variant, R: MemoryReclaimer<V>> Default
20    for MemoryReclaimOnThreshold<D, V, R>
21{
22    fn default() -> Self {
23        Self {
24            phantom: Default::default(),
25        }
26    }
27}
28
29impl<const D: usize, V: Variant, R: MemoryReclaimer<V>> Clone
30    for MemoryReclaimOnThreshold<D, V, R>
31{
32    fn clone(&self) -> Self {
33        Self::default()
34    }
35}
36
37impl<const D: usize, V: Variant, R: MemoryReclaimer<V>> MemoryReclaimOnThreshold<D, V, R> {
38    /// Returns whether or not the collection `col` requires to reclaim memory; i.e.,
39    /// whether or not the utilization is below the constant threshold.
40    pub fn col_needs_memory_reclaim<P>(col: &SelfRefCol<V, Self, P>) -> bool
41    where
42        P: PinnedVec<Node<V>>,
43    {
44        let num_active_nodes = col.len();
45        let used = col.nodes().len();
46        let allowed_vacant = used >> D;
47        let num_vacant = used - num_active_nodes;
48
49        num_vacant > allowed_vacant
50    }
51}
52
53impl<const D: usize, V, R> MemoryPolicy<V> for MemoryReclaimOnThreshold<D, V, R>
54where
55    V: Variant,
56    R: MemoryReclaimer<V>,
57{
58    fn reclaim_closed_nodes<P>(col: &mut CoreCol<V, P>, _closed_node_ptr: &NodePtr<V>) -> bool
59    where
60        P: PinnedVec<Node<V>>,
61    {
62        let num_active_nodes = col.len();
63        let used = col.nodes().len();
64        let allowed_vacant = used >> D;
65        let num_vacant = used - num_active_nodes;
66
67        match num_vacant <= allowed_vacant {
68            true => false,
69            false => {
70                let nodes_moved = R::reclaim_nodes(col);
71                col.nodes_mut().truncate(num_active_nodes);
72                nodes_moved
73            }
74        }
75    }
76}