cranpose_core/snapshot_v2/
nested.rs1use super::*;
2
3pub struct NestedReadonlySnapshot {
13 pub(super) state: SnapshotState,
14 parent: Weak<NestedReadonlySnapshot>,
15}
16
17impl NestedReadonlySnapshot {
18 pub fn new(
22 id: SnapshotId,
23 invalid: SnapshotIdSet,
24 read_observer: Option<ReadObserver>,
25 parent: Weak<NestedReadonlySnapshot>,
26 ) -> Rc<Self> {
27 Rc::new(Self {
28 state: SnapshotState::new(id, invalid, read_observer, None, false),
29 parent,
30 })
31 }
32
33 pub fn snapshot_id(&self) -> SnapshotId {
35 self.state.id.get()
36 }
37
38 pub fn invalid(&self) -> SnapshotIdSet {
40 self.state.invalid.borrow().clone()
41 }
42
43 pub fn read_only(&self) -> bool {
45 true
46 }
47
48 pub fn root_nested_readonly(&self) -> Rc<NestedReadonlySnapshot> {
51 if let Some(parent) = self.parent.upgrade() {
52 parent.root_nested_readonly()
53 } else {
54 NestedReadonlySnapshot::new(
55 self.state.id.get(),
56 self.state.invalid.borrow().clone(),
57 self.state.read_observer.borrow().clone(),
58 Weak::new(),
59 )
60 }
61 }
62
63 pub fn enter<T>(self: &Rc<Self>, f: impl FnOnce() -> T) -> T {
66 enter_snapshot_scope(AnySnapshot::NestedReadonly(self.clone()), f)
67 }
68
69 pub fn take_nested_snapshot(
72 &self,
73 read_observer: Option<ReadObserver>,
74 ) -> Rc<NestedReadonlySnapshot> {
75 let merged_observer =
76 merge_read_observers(read_observer, self.state.read_observer.borrow().clone());
77
78 NestedReadonlySnapshot::new(
79 self.state.id.get(),
80 self.state.invalid.borrow().clone(),
81 merged_observer,
82 self.parent.clone(),
83 )
84 }
85
86 pub fn has_pending_changes(&self) -> bool {
88 false
89 }
90
91 pub fn dispose(&self) {
93 if !self.state.disposed.get() {
94 self.state.dispose();
95 }
96 }
97
98 pub fn record_read(&self, state: &dyn StateObject) {
100 self.state.record_read(state);
101 }
102
103 pub fn record_write(&self, _state: Rc<dyn StateObject>) {
105 panic!("Cannot write to a read-only snapshot");
106 }
107
108 pub fn is_disposed(&self) -> bool {
110 self.state.disposed.get()
111 }
112}
113
114pub struct NestedMutableSnapshot {
125 pub(super) state: SnapshotState,
126 parent: Weak<MutableSnapshot>,
127 nested_count: Cell<usize>,
128 applied: Cell<bool>,
129 base_parent_id: SnapshotId,
130}
131
132impl NestedMutableSnapshot {
133 pub fn new(
136 id: SnapshotId,
137 invalid: SnapshotIdSet,
138 read_observer: Option<ReadObserver>,
139 write_observer: Option<WriteObserver>,
140 parent: Weak<MutableSnapshot>,
141 base_parent_id: SnapshotId,
142 ) -> Rc<Self> {
143 Rc::new(Self {
144 state: SnapshotState::new(id, invalid, read_observer, write_observer, true),
145 parent,
146 nested_count: Cell::new(0),
147 applied: Cell::new(false),
148 base_parent_id,
149 })
150 }
151
152 pub fn snapshot_id(&self) -> SnapshotId {
154 self.state.id.get()
155 }
156
157 pub fn invalid(&self) -> SnapshotIdSet {
159 self.state.invalid.borrow().clone()
160 }
161
162 pub fn read_only(&self) -> bool {
164 false
165 }
166
167 pub(crate) fn set_on_dispose<F>(&self, f: F)
168 where
169 F: FnOnce() + 'static,
170 {
171 self.state.set_on_dispose(f);
172 }
173
174 pub fn root_mutable(&self) -> Rc<MutableSnapshot> {
177 if let Some(parent) = self.parent.upgrade() {
178 parent.root_mutable()
179 } else {
180 MutableSnapshot::new(
181 self.state.id.get(),
182 self.state.invalid.borrow().clone(),
183 self.state.read_observer.borrow().clone(),
184 self.state.write_observer.borrow().clone(),
185 self.base_parent_id,
186 )
187 }
188 }
189
190 pub fn enter<T>(self: &Rc<Self>, f: impl FnOnce() -> T) -> T {
193 enter_snapshot_scope(AnySnapshot::NestedMutable(self.clone()), f)
194 }
195
196 pub fn take_nested_snapshot(
199 &self,
200 read_observer: Option<ReadObserver>,
201 ) -> Rc<ReadonlySnapshot> {
202 let merged_observer =
203 merge_read_observers(read_observer, self.state.read_observer.borrow().clone());
204
205 ReadonlySnapshot::new(
206 self.state.id.get(),
207 self.state.invalid.borrow().clone(),
208 merged_observer,
209 )
210 }
211
212 pub fn has_pending_changes(&self) -> bool {
214 !self.state.modified.borrow().is_empty()
215 }
216
217 pub fn pending_children(&self) -> Vec<SnapshotId> {
219 self.state.pending_children()
220 }
221
222 pub fn has_pending_children(&self) -> bool {
224 self.state.has_pending_children()
225 }
226
227 pub fn dispose(&self) {
230 if !self.state.disposed.get() && self.nested_count.get() == 0 {
231 self.state.dispose();
232 }
233 }
234
235 pub fn record_read(&self, state: &dyn StateObject) {
237 self.state.record_read(state);
238 }
239
240 pub fn record_write(&self, state: Rc<dyn StateObject>) {
243 assert!(!self.applied.get(), "Cannot write to an applied snapshot");
244 assert!(
245 !self.state.disposed.get(),
246 "Cannot write to a disposed snapshot"
247 );
248 self.state.record_write(state, self.state.id.get());
249 }
250
251 pub fn is_disposed(&self) -> bool {
253 self.state.disposed.get()
254 }
255
256 pub fn apply(&self) -> SnapshotApplyResult {
260 if self.state.disposed.get() {
261 return SnapshotApplyResult::Failure;
262 }
263
264 if self.applied.get() {
265 return SnapshotApplyResult::Failure;
266 }
267
268 if let Some(parent) = self.parent.upgrade() {
269 let child_modified = self.state.modified.borrow();
270 if child_modified.is_empty() {
271 self.applied.set(true);
272 self.state.dispose();
273 return SnapshotApplyResult::Success;
274 }
275 if parent.merge_child_modifications(&child_modified).is_err() {
276 return SnapshotApplyResult::Failure;
277 }
278
279 self.applied.set(true);
280 self.state.dispose();
281 SnapshotApplyResult::Success
282 } else {
283 SnapshotApplyResult::Failure
284 }
285 }
286
287 pub fn take_nested_mutable_snapshot(
290 self: &Rc<Self>,
291 read_observer: Option<ReadObserver>,
292 write_observer: Option<WriteObserver>,
293 ) -> Rc<NestedMutableSnapshot> {
294 let root = Rc::downgrade(&self.root_mutable());
295 allocate_nested_mutable_snapshot(self, root, read_observer, write_observer)
296 }
297}
298
299impl NestedMutableHost for NestedMutableSnapshot {
300 fn snapshot_state(&self) -> &SnapshotState {
301 &self.state
302 }
303
304 fn nested_count(&self) -> &Cell<usize> {
305 &self.nested_count
306 }
307}
308
309#[cfg(test)]
310#[path = "tests/nested_tests.rs"]
311mod tests;