Skip to main content

cranpose_core/slot/
table.rs

1use super::{
2    AnchorRegistry, DeferredDrop, GroupRecord, MovableIndex, NodeRecord, PayloadAnchorRegistry,
3    SlotLifecycleCoordinator, SlotWriteSessionState, debug::SlotTableDiagnostics,
4    payload_store::PayloadStore,
5};
6use crate::collections::growth_slack::GrowthSlack;
7
8mod metadata;
9mod mutation;
10mod values;
11
12#[cfg(test)]
13pub(crate) use values::ValueSlotError;
14
15// A table's number, which no other table of its thread takes: maps key
16// hosts by it and a value slot names its table by it, so a table made where
17// a dropped one lay is not taken for it, and the maps' order does not follow
18// the heap's layout.
19struct SlotStorageIdentity(usize);
20
21impl SlotStorageIdentity {
22    fn new() -> Self {
23        crate::thread_state::cells(|cells| {
24            let id = cells.next_slot_storage_id.get();
25            cells.next_slot_storage_id.set(id + 1);
26            Self(id)
27        })
28    }
29
30    fn id(&self) -> usize {
31        self.0
32    }
33}
34
35pub(crate) struct SlotWriteSession<'a> {
36    pub(super) table: &'a mut SlotTable,
37    pub(in crate::slot) lifecycle: &'a mut SlotLifecycleCoordinator,
38    pub(in crate::slot) state: &'a mut SlotWriteSessionState,
39}
40
41/// Storage for the groups, remembered values and nodes that one composition produced.
42pub struct SlotTable {
43    storage_id: SlotStorageIdentity,
44    pub(super) groups: Vec<GroupRecord>,
45    pub(super) payloads: PayloadStore,
46    pub(super) nodes: Vec<NodeRecord>,
47    pub(super) anchors: AnchorRegistry,
48    pub(super) payload_anchors: PayloadAnchorRegistry,
49    pub(super) movables: MovableIndex,
50    pub(super) diagnostics: SlotTableDiagnostics,
51    stale_group_indexes: metadata::StaleGroupIndexes,
52    next_group_generation: u32,
53}
54
55impl SlotTable {
56    /// Creates an empty table.
57    pub fn new() -> Self {
58        Self {
59            storage_id: SlotStorageIdentity::new(),
60            groups: Vec::new(),
61            payloads: PayloadStore::default(),
62            nodes: Vec::new(),
63            anchors: AnchorRegistry::new(),
64            payload_anchors: PayloadAnchorRegistry::new(),
65            movables: MovableIndex::default(),
66            diagnostics: Default::default(),
67            stale_group_indexes: metadata::StaleGroupIndexes::default(),
68            next_group_generation: 1,
69        }
70    }
71
72    pub(crate) fn write_session<'a>(
73        &'a mut self,
74        lifecycle: &'a mut SlotLifecycleCoordinator,
75        state: &'a mut SlotWriteSessionState,
76    ) -> SlotWriteSession<'a> {
77        SlotWriteSession {
78            table: self,
79            lifecycle,
80            state,
81        }
82    }
83
84    pub(crate) fn storage_id(&self) -> usize {
85        self.storage_id.id()
86    }
87
88    #[cfg(test)]
89    pub(in crate::slot) fn set_next_group_generation_for_test(&mut self, generation: u32) {
90        self.next_group_generation = generation;
91    }
92
93    #[cfg(test)]
94    pub(in crate::slot) fn set_next_group_anchor_for_test(&mut self, next_anchor: usize) {
95        self.anchors.set_next_anchor_for_test(next_anchor);
96    }
97
98    #[cfg(test)]
99    pub(in crate::slot) fn set_next_payload_anchor_for_test(&mut self, next_anchor: usize) {
100        self.payload_anchors.set_next_id_for_test(next_anchor);
101    }
102
103    pub(crate) fn compact_storage(&mut self) {
104        self.groups.shrink_to_fit();
105        self.payloads.compact();
106        self.nodes.shrink_to_fit();
107        self.anchors.shrink_to_fit();
108        self.payload_anchors.shrink_to_fit();
109        self.movables.shrink_to_fit();
110    }
111
112    pub(crate) fn storage_capacity(&self) -> usize {
113        self.groups.capacity() + self.payloads.capacity() + self.nodes.capacity()
114    }
115
116    pub(crate) fn trim_growth_slack(&mut self) {
117        self.groups.trim_growth_slack();
118        self.payloads.trim_growth_slack();
119        self.nodes.trim_growth_slack();
120        self.anchors.trim_growth_slack();
121        self.payload_anchors.trim_growth_slack();
122    }
123
124    pub(crate) fn take_effect_drops(&mut self) -> Vec<DeferredDrop> {
125        let mut drops = Vec::new();
126        self.payloads.for_each_mut(|payload| {
127            if let Some(fresh) = payload.payload_type.fresh {
128                let old = std::mem::replace(&mut payload.value, fresh());
129                drops.push(DeferredDrop::payload(old));
130            }
131        });
132        drops
133    }
134
135    pub(crate) fn take_all_drops(&mut self) -> Vec<DeferredDrop> {
136        let mut drops = Vec::with_capacity(self.payloads.len());
137        self.payloads
138            .drain_rev(|payload| drops.push(payload.into_deferred_drop()));
139        self.groups.clear();
140        self.stale_group_indexes = metadata::StaleGroupIndexes::default();
141        self.nodes.clear();
142        self.anchors.clear();
143        self.payload_anchors.clear();
144        self.movables.clear();
145        drops
146    }
147}
148
149impl Default for SlotTable {
150    fn default() -> Self {
151        Self::new()
152    }
153}