cranpose_core/snapshot_v2/
transparent.rs1use super::*;
2
3pub struct TransparentObserverMutableSnapshot {
13 pub(super) state: SnapshotState,
14 parent: Option<Weak<Self>>,
15 nested_count: Cell<usize>,
16 applied: Cell<bool>,
17 reusable: Cell<bool>,
18}
19
20impl TransparentObserverMutableSnapshot {
21 pub fn new(
25 id: SnapshotId,
26 invalid: SnapshotIdSet,
27 read_observer: Option<ReadObserver>,
28 write_observer: Option<WriteObserver>,
29 parent: Option<Weak<Self>>,
30 ) -> Rc<Self> {
31 Self::new_reusing(None, id, invalid, read_observer, write_observer, parent)
32 }
33
34 pub(crate) fn new_reusing(
35 recycled: Option<Rc<Self>>,
36 id: SnapshotId,
37 invalid: SnapshotIdSet,
38 read_observer: Option<ReadObserver>,
39 write_observer: Option<WriteObserver>,
40 parent: Option<Weak<Self>>,
41 ) -> Rc<Self> {
42 let fresh = Self {
43 state: SnapshotState::new_with_pinning(
44 id,
45 invalid,
46 read_observer,
47 write_observer,
48 RuntimeTracking::Untracked,
49 Pinning::Unpinned,
50 ),
51 parent,
52 nested_count: Cell::new(0),
53 applied: Cell::new(false),
54 reusable: Cell::new(true),
55 };
56 if let Some(mut recycled) = recycled
57 && let Some(target) = Rc::get_mut(&mut recycled)
58 {
59 *target = fresh;
60 recycled
61 } else {
62 Rc::new(fresh)
63 }
64 }
65
66 pub fn can_reuse(&self) -> bool {
68 self.reusable.get()
69 }
70
71 pub(crate) fn observers(&self) -> (Option<ReadObserver>, Option<WriteObserver>) {
72 (
73 self.state.read_observer.borrow().clone(),
74 self.state.write_observer.borrow().clone(),
75 )
76 }
77
78 pub(crate) fn reads_into(&self, observer: &ReadObserver) -> bool {
79 self.state
80 .read_observer
81 .borrow()
82 .as_ref()
83 .is_some_and(|installed| Rc::ptr_eq(installed, observer))
84 }
85
86 pub fn set_read_observer(&self, observer: Option<ReadObserver>) {
88 assert!(
89 self.can_reuse(),
90 "Cannot change observers on non-reusable snapshot"
91 );
92 *self.state.read_observer.borrow_mut() = observer;
93 }
94
95 pub fn set_write_observer(&self, observer: Option<WriteObserver>) {
97 assert!(
98 self.can_reuse(),
99 "Cannot change observers on non-reusable snapshot"
100 );
101 *self.state.write_observer.borrow_mut() = observer;
102 }
103
104 pub fn snapshot_id(&self) -> SnapshotId {
106 self.state.id.get()
107 }
108
109 pub fn invalid(&self) -> SnapshotIdSet {
111 self.state.invalid.borrow().clone()
112 }
113
114 pub fn read_only(&self) -> bool {
116 false
117 }
118
119 pub fn root_transparent_mutable(self: &Rc<Self>) -> Rc<Self> {
121 match &self.parent {
122 Some(weak) => weak.upgrade().map_or_else(
123 || Rc::clone(self),
124 |parent| parent.root_transparent_mutable(),
125 ),
126 None => Rc::clone(self),
127 }
128 }
129
130 pub fn enter<T>(self: &Rc<Self>, f: impl FnOnce() -> T) -> T {
134 let prev = current_snapshot();
135
136 if let Some(ref snapshot) = prev
137 && snapshot.is_same_transparent(self)
138 {
139 return f();
140 }
141
142 enter_snapshot_scope(AnySnapshot::TransparentMutable(Rc::clone(self)), f)
143 }
144
145 pub fn take_nested_snapshot(
148 &self,
149 read_observer: Option<ReadObserver>,
150 ) -> Rc<ReadonlySnapshot> {
151 let merged_observer =
152 merge_read_observers(read_observer, self.state.read_observer.borrow().clone());
153 ReadonlySnapshot::new(
154 self.state.id.get(),
155 self.state.invalid.borrow().clone(),
156 merged_observer,
157 )
158 }
159
160 pub fn has_pending_changes(&self) -> bool {
162 !self.state.modified.borrow().is_empty()
163 }
164
165 pub fn dispose(&self) {
168 if !self.state.disposed.get() && self.nested_count.get() == 0 {
169 self.state.dispose();
170 }
171 }
172
173 pub fn record_read(&self, state: &dyn StateObject) {
175 self.state.record_read(state);
176 }
177
178 pub fn record_write(&self, state: Rc<dyn StateObject>) {
181 assert!(!self.applied.get(), "Cannot write to an applied snapshot");
182 self.state.record_write(state, self.state.id.get());
183 }
184
185 pub fn is_disposed(&self) -> bool {
187 self.state.disposed.get()
188 }
189
190 pub fn apply(&self) -> SnapshotApplyResult {
192 if self.state.disposed.get() || self.applied.get() {
193 return SnapshotApplyResult::Failure;
194 }
195
196 self.applied.set(true);
197 SnapshotApplyResult::Success
198 }
199
200 pub fn take_nested_mutable_snapshot(
203 &self,
204 read_observer: Option<ReadObserver>,
205 write_observer: Option<WriteObserver>,
206 ) -> Rc<Self> {
207 let merged_read =
208 merge_read_observers(read_observer, self.state.read_observer.borrow().clone());
209 let merged_write =
210 merge_write_observers(write_observer, self.state.write_observer.borrow().clone());
211
212 let mut invalid = self.state.invalid.borrow().clone();
213 let new_id = self.state.id.get().next();
214 invalid = invalid.set(new_id);
215
216 Self::new(
217 new_id,
218 invalid,
219 merged_read,
220 merged_write,
221 self.parent.clone(),
222 )
223 }
224}
225
226pub struct TransparentObserverSnapshot {
235 pub(super) state: SnapshotState,
236 parent: Option<Weak<Self>>,
237 reusable: Cell<bool>,
238}
239
240impl TransparentObserverSnapshot {
241 pub fn new(
245 id: SnapshotId,
246 invalid: SnapshotIdSet,
247 read_observer: Option<ReadObserver>,
248 parent: Option<Weak<Self>>,
249 ) -> Rc<Self> {
250 Rc::new(Self {
251 state: SnapshotState::new_with_pinning(
252 id,
253 invalid,
254 read_observer,
255 None,
256 RuntimeTracking::Untracked,
257 Pinning::Unpinned,
258 ),
259 parent,
260 reusable: Cell::new(true),
261 })
262 }
263
264 pub fn can_reuse(&self) -> bool {
266 self.reusable.get()
267 }
268
269 pub fn set_read_observer(&self, observer: Option<ReadObserver>) {
271 assert!(
272 self.can_reuse(),
273 "Cannot change observers on non-reusable snapshot"
274 );
275 *self.state.read_observer.borrow_mut() = observer;
276 }
277
278 pub fn snapshot_id(&self) -> SnapshotId {
280 self.state.id.get()
281 }
282
283 pub fn invalid(&self) -> SnapshotIdSet {
285 self.state.invalid.borrow().clone()
286 }
287
288 pub fn read_only(&self) -> bool {
290 true
291 }
292
293 pub fn root_transparent_readonly(self: &Rc<Self>) -> Rc<Self> {
295 match &self.parent {
296 Some(weak) => weak.upgrade().map_or_else(
297 || Rc::clone(self),
298 |parent| parent.root_transparent_readonly(),
299 ),
300 None => Rc::clone(self),
301 }
302 }
303
304 pub fn enter<T>(self: &Rc<Self>, f: impl FnOnce() -> T) -> T {
308 let previous = current_snapshot();
309
310 if let Some(ref prev_snapshot) = previous
311 && prev_snapshot.is_same_transparent_readonly(self)
312 {
313 return f();
314 }
315
316 enter_snapshot_scope(AnySnapshot::TransparentReadonly(Rc::clone(self)), f)
317 }
318
319 pub fn take_nested_snapshot(&self, read_observer: Option<ReadObserver>) -> Rc<Self> {
322 let merged_observer =
323 merge_read_observers(read_observer, self.state.read_observer.borrow().clone());
324 Self::new(
325 self.state.id.get(),
326 self.state.invalid.borrow().clone(),
327 merged_observer,
328 self.parent.clone(),
329 )
330 }
331
332 pub fn has_pending_changes(&self) -> bool {
334 false
335 }
336
337 pub fn dispose(&self) {
339 self.state.dispose();
340 }
341
342 pub fn record_read(&self, state: &dyn StateObject) {
344 self.state.record_read(state);
345 }
346
347 pub fn record_write(&self, _state: Rc<dyn StateObject>) {
349 panic!("Cannot write to a read-only snapshot");
350 }
351
352 pub fn is_disposed(&self) -> bool {
354 self.state.disposed.get()
355 }
356}
357
358#[cfg(test)]
359#[path = "tests/transparent_tests.rs"]
360mod tests;