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}