oxidd_manager_pointer/terminal_manager/
mod.rs

1use std::borrow::Borrow;
2use std::hash::Hash;
3use std::ptr::NonNull;
4
5use oxidd_core::util::AllocResult;
6
7use crate::manager::Edge;
8
9mod r#static;
10pub use r#static::*;
11
12/// Manager for terminal nodes
13///
14/// # Safety
15///
16/// [`TerminalManager::new_in()`] must properly initialize the given slot and
17/// return a reference to the initialized slot.
18pub unsafe trait TerminalManager<
19    'id,
20    InnerNode,
21    EdgeTag,
22    ManagerData,
23    const PAGE_SIZE: usize,
24    const TAG_BITS: u32,
25>: Sized
26{
27    type TerminalNode: Eq + Hash;
28    type TerminalNodeRef<'a>: Borrow<Self::TerminalNode> + Copy
29    where
30        Self: 'a;
31
32    type Iterator<'a>: Iterator<Item = Edge<'id, InnerNode, EdgeTag, TAG_BITS>>
33    where
34        Self: 'a;
35
36    /// Create a new `TerminalManager` in the given `slot`
37    ///
38    /// # Safety
39    ///
40    /// `slot` is valid for writes and properly aligned. When returning from
41    /// this function, the location referenced by `slot` is initialized. With
42    /// respect to Stacked / Tree borrows, `slot` is tagged as the root of the
43    /// allocation.
44    unsafe fn new_in(slot: *mut Self);
45
46    /// Get a pointer to the terminal store
47    fn terminal_manager(edge: &Edge<'id, InnerNode, EdgeTag, TAG_BITS>) -> NonNull<Self>;
48
49    /// Get the number of currently stored terminals
50    #[must_use]
51    fn len(&self) -> usize;
52
53    /// Returns `true` iff currently no terminals are stored
54    #[must_use]
55    fn is_empty(&self) -> bool {
56        self.len() == 0
57    }
58
59    /// Dereference the given `edge`
60    fn deref_edge(
61        &self,
62        edge: &Edge<'id, InnerNode, EdgeTag, TAG_BITS>,
63    ) -> Self::TerminalNodeRef<'_>;
64
65    /// Clone the given `edge`
66    fn clone_edge(
67        edge: &Edge<'id, InnerNode, EdgeTag, TAG_BITS>,
68    ) -> Edge<'id, InnerNode, EdgeTag, TAG_BITS>;
69
70    /// Drop the given `edge`
71    fn drop_edge(edge: Edge<'id, InnerNode, EdgeTag, TAG_BITS>);
72
73    /// Add a terminal to this manager (if it does not already exist) and return
74    /// an [`Edge`] pointing to it
75    ///
76    /// # Safety
77    ///
78    /// `this` is valid for reads, properly aligned and initialized. With
79    /// respect to Stacked / Tree Borrows, `this` is tagged as the root of the
80    /// allocation.
81    unsafe fn get(
82        this: *const Self,
83        terminal: Self::TerminalNode,
84    ) -> AllocResult<Edge<'id, InnerNode, EdgeTag, TAG_BITS>>;
85
86    /// Iterate over all terminals
87    ///
88    /// # Safety
89    ///
90    /// `this` is valid for reads, properly aligned and initialized during `'a`.
91    /// With respect to Stacked / Tree Borrows, `this` is tagged as the root of
92    /// the allocation.
93    unsafe fn iter<'a>(this: *const Self) -> Self::Iterator<'a>
94    where
95        Self: 'a;
96
97    /// Garbage collection: remove unused terminals
98    fn gc(&self) -> usize;
99}