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
19/// # SAFETY:
20///
21/// Memory reclaimers are zero-sized static types.
22unsafe impl<const D: usize, V: Variant, R: MemoryReclaimer<V>> Sync
23    for MemoryReclaimOnThreshold<D, V, R>
24{
25}
26
27impl<const D: usize, V: Variant, R: MemoryReclaimer<V>> Default
28    for MemoryReclaimOnThreshold<D, V, R>
29{
30    fn default() -> Self {
31        Self {
32            phantom: Default::default(),
33        }
34    }
35}
36
37impl<const D: usize, V: Variant, R: MemoryReclaimer<V>> Clone
38    for MemoryReclaimOnThreshold<D, V, R>
39{
40    fn clone(&self) -> Self {
41        Self::default()
42    }
43}
44
45impl<const D: usize, V: Variant, R: MemoryReclaimer<V>> MemoryReclaimOnThreshold<D, V, R> {
46    /// Returns whether or not the collection `col` requires to reclaim memory; i.e.,
47    /// whether or not the utilization is below the constant threshold.
48    pub fn col_needs_memory_reclaim<P>(col: &SelfRefCol<V, Self, P>) -> bool
49    where
50        P: PinnedVec<Node<V>>,
51    {
52        let num_active_nodes = col.len();
53        let used = col.nodes().len();
54        let allowed_vacant = used >> D;
55        let num_vacant = used - num_active_nodes;
56
57        num_vacant > allowed_vacant
58    }
59}
60
61impl<const D: usize, V, R> MemoryPolicy<V> for MemoryReclaimOnThreshold<D, V, R>
62where
63    V: Variant,
64    R: MemoryReclaimer<V>,
65{
66    fn reclaim_closed_nodes<P>(col: &mut CoreCol<V, P>, _closed_node_ptr: NodePtr<V>) -> bool
67    where
68        P: PinnedVec<Node<V>>,
69    {
70        let num_active_nodes = col.len();
71        let used = col.nodes().len();
72        let allowed_vacant = used >> D;
73        let num_vacant = used - num_active_nodes;
74
75        match num_vacant <= allowed_vacant {
76            true => false,
77            false => {
78                let nodes_moved = R::reclaim_nodes(col);
79                col.nodes_mut().truncate(num_active_nodes);
80                nodes_moved
81            }
82        }
83    }
84}