cranpose_core/snapshot_v2/
nested.rs1use super::*;
2
3pub struct NestedReadonlySnapshot {
13 pub(super) state: SnapshotState,
14 parent: Weak<Self>,
15}
16
17impl NestedReadonlySnapshot {
18 pub fn new(
22 id: SnapshotId,
23 invalid: SnapshotIdSet,
24 read_observer: Option<ReadObserver>,
25 parent: Weak<Self>,
26 ) -> Rc<Self> {
27 Rc::new(Self {
28 state: SnapshotState::new(id, invalid, read_observer, None, RuntimeTracking::Untracked),
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<Self> {
51 if let Some(parent) = self.parent.upgrade() {
52 parent.root_nested_readonly()
53 } else {
54 Self::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(Rc::clone(self)), f)
67 }
68
69 pub fn take_nested_snapshot(&self, read_observer: Option<ReadObserver>) -> Rc<Self> {
72 let merged_observer =
73 merge_read_observers(read_observer, self.state.read_observer.borrow().clone());
74
75 Self::new(
76 self.state.id.get(),
77 self.state.invalid.borrow().clone(),
78 merged_observer,
79 Weak::clone(&self.parent),
80 )
81 }
82
83 pub fn has_pending_changes(&self) -> bool {
85 false
86 }
87
88 pub fn dispose(&self) {
90 if !self.state.disposed.get() {
91 self.state.dispose();
92 }
93 }
94
95 pub fn record_read(&self, state: &dyn StateObject) {
97 self.state.record_read(state);
98 }
99
100 pub fn record_write(&self, _state: Rc<dyn StateObject>) {
102 panic!("Cannot write to a read-only snapshot");
103 }
104
105 pub fn is_disposed(&self) -> bool {
107 self.state.disposed.get()
108 }
109}
110
111pub struct NestedMutableSnapshot {
122 pub(super) state: SnapshotState,
123 parent: Weak<MutableSnapshot>,
124 nested_count: Cell<usize>,
125 applied: Cell<bool>,
126 base_parent_id: SnapshotId,
127}
128
129impl NestedMutableSnapshot {
130 pub fn new(
133 id: SnapshotId,
134 invalid: SnapshotIdSet,
135 read_observer: Option<ReadObserver>,
136 write_observer: Option<WriteObserver>,
137 parent: Weak<MutableSnapshot>,
138 base_parent_id: SnapshotId,
139 ) -> Rc<Self> {
140 Rc::new(Self {
141 state: SnapshotState::new(
142 id,
143 invalid,
144 read_observer,
145 write_observer,
146 RuntimeTracking::Tracked,
147 ),
148 parent,
149 nested_count: Cell::new(0),
150 applied: Cell::new(false),
151 base_parent_id,
152 })
153 }
154
155 pub fn snapshot_id(&self) -> SnapshotId {
157 self.state.id.get()
158 }
159
160 pub fn invalid(&self) -> SnapshotIdSet {
162 self.state.invalid.borrow().clone()
163 }
164
165 pub fn read_only(&self) -> bool {
167 false
168 }
169
170 pub(crate) fn set_on_dispose<F>(&self, f: F)
171 where
172 F: FnOnce() + 'static,
173 {
174 self.state.set_on_dispose(f);
175 }
176
177 pub fn root_mutable(&self) -> Rc<MutableSnapshot> {
180 if let Some(parent) = self.parent.upgrade() {
181 parent.root_mutable()
182 } else {
183 MutableSnapshot::new(
184 self.state.id.get(),
185 self.state.invalid.borrow().clone(),
186 self.state.read_observer.borrow().clone(),
187 self.state.write_observer.borrow().clone(),
188 self.base_parent_id,
189 )
190 }
191 }
192
193 pub fn enter<T>(self: &Rc<Self>, f: impl FnOnce() -> T) -> T {
196 enter_snapshot_scope(AnySnapshot::NestedMutable(Rc::clone(self)), f)
197 }
198
199 pub fn take_nested_snapshot(
202 &self,
203 read_observer: Option<ReadObserver>,
204 ) -> Rc<ReadonlySnapshot> {
205 let merged_observer =
206 merge_read_observers(read_observer, self.state.read_observer.borrow().clone());
207
208 ReadonlySnapshot::new(
209 self.state.id.get(),
210 self.state.invalid.borrow().clone(),
211 merged_observer,
212 )
213 }
214
215 pub fn has_pending_changes(&self) -> bool {
217 !self.state.modified.borrow().is_empty()
218 }
219
220 pub fn pending_children(&self) -> Vec<SnapshotId> {
222 self.state.pending_children()
223 }
224
225 pub fn has_pending_children(&self) -> bool {
227 self.state.has_pending_children()
228 }
229
230 pub fn dispose(&self) {
233 if !self.state.disposed.get() && self.nested_count.get() == 0 {
234 self.state.dispose();
235 }
236 }
237
238 pub fn record_read(&self, state: &dyn StateObject) {
240 self.state.record_read(state);
241 }
242
243 pub fn record_write(&self, state: Rc<dyn StateObject>) {
246 assert!(!self.applied.get(), "Cannot write to an applied snapshot");
247 assert!(
248 !self.state.disposed.get(),
249 "Cannot write to a disposed snapshot"
250 );
251 self.state.record_write(state, self.state.id.get());
252 }
253
254 pub fn is_disposed(&self) -> bool {
256 self.state.disposed.get()
257 }
258
259 pub fn apply(&self) -> SnapshotApplyResult {
263 if self.state.disposed.get() {
264 return SnapshotApplyResult::Failure;
265 }
266
267 if self.applied.get() {
268 return SnapshotApplyResult::Failure;
269 }
270
271 if let Some(parent) = self.parent.upgrade() {
272 let child_modified = self.state.modified.borrow();
273 if child_modified.is_empty() {
274 self.applied.set(true);
275 self.state.dispose();
276 return SnapshotApplyResult::Success;
277 }
278 if parent.merge_child_modifications(&child_modified).is_err() {
279 return SnapshotApplyResult::Failure;
280 }
281
282 self.applied.set(true);
283 self.state.dispose();
284 SnapshotApplyResult::Success
285 } else {
286 SnapshotApplyResult::Failure
287 }
288 }
289
290 pub fn take_nested_mutable_snapshot(
293 self: &Rc<Self>,
294 read_observer: Option<ReadObserver>,
295 write_observer: Option<WriteObserver>,
296 ) -> Rc<Self> {
297 let root = Rc::downgrade(&self.root_mutable());
298 allocate_nested_mutable_snapshot(self, root, read_observer, write_observer)
299 }
300}
301
302impl NestedMutableHost for NestedMutableSnapshot {
303 fn snapshot_state(&self) -> &SnapshotState {
304 &self.state
305 }
306
307 fn nested_count(&self) -> &Cell<usize> {
308 &self.nested_count
309 }
310}
311
312#[cfg(test)]
313#[path = "tests/nested_tests.rs"]
314mod tests;