1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
use std::collections::HashSet;
use crate::node::NodePtr;
use crate::BTreeStore;
/// Extension to tracing garbage-collect nodes in a store
pub trait BTreeStoreExt<K, V> {
/// Remove all allocated nodes which are not reachable through `b_trees` iterator.
///
/// # Safety
/// `b_trees` *must* return b-trees containing all reachable nodes in the store, AKA there must
/// not exist a b-tree with this store which is not in `b_trees`. Any nodes not reachable through
/// `b_trees` will be dropped.
unsafe fn tracing_gc<'a>(&self, btrees: impl IntoIterator<Item = impl BTree<'a, K, V>>)
where
K: 'a,
V: 'a;
// TODO: Async or background version which does [tri-color marking](https://en.wikipedia.org/wiki/Tracing_garbage_collection#Tri-color_marking)
}
/// Generic trait for different b-tree maps and sets, which returns reachable nodes.
///
/// This trait is [sealed](https://rust-lang.github.io/api-guidelines/future-proofing.html#sealed-traits-protect-against-downstream-implementations-c-sealed)
pub trait BTree<'store, K, V>: crate::copyable::sealed::BTree<'store, K, V> {}
impl<K, V> BTreeStoreExt<K, V> for BTreeStore<K, V> {
#[inline]
unsafe fn tracing_gc<'a>(&self, b_trees: impl IntoIterator<Item = impl BTree<'a, K, V>>)
where
K: 'a,
V: 'a,
{
let nodes = b_trees
.into_iter()
.flat_map(|b_tree| {
b_tree.assert_store(self);
b_tree.nodes()
})
.collect::<HashSet<_>>();
self.retain_shared(|node| nodes.contains(&NodePtr::from_ref(node)));
}
}