duat_core/data/rw.rs
1use std::{
2 any::TypeId,
3 sync::{
4 Arc,
5 atomic::{AtomicUsize, Ordering},
6 },
7};
8
9use super::{Data, RoData, RwLock, RwLockReadGuard, RwLockWriteGuard, private::InnerData};
10
11/// A read write shared reference to data
12pub struct RwData<T: ?Sized + 'static> {
13 // The `Box` is to allow for downcasting.
14 pub(super) data: Arc<RwLock<T>>,
15 pub(super) cur_state: Arc<AtomicUsize>,
16 read_state: AtomicUsize,
17 pub(super) type_id: TypeId,
18}
19
20impl<T> RwData<T> {
21 /// Returns a new instance of a [`RwData`], assuming that it is
22 /// sized.
23 ///
24 /// This has to be sized because of some Rust limitations, as you
25 /// can`t really pass an unsized argument to a function (for now).
26 /// If you're looking to store unsized types (`dyn Trait`,
27 /// `\[Type\]`, etc) on an [`RwData`], see
28 /// [`RwData::new_unsized`].
29 pub fn new(data: T) -> Self {
30 Self {
31 data: Arc::new(RwLock::new(data)),
32 cur_state: Arc::new(AtomicUsize::new(1)),
33 read_state: AtomicUsize::new(1),
34 type_id: TypeId::of::<T>(),
35 }
36 }
37}
38
39impl<T: ?Sized> RwData<T> {
40 /// Returns a new instance of [`RwData`], assuming that it is
41 /// unsized.
42 ///
43 /// This method is only required if you're dealing with types that
44 /// may not be [`Sized`] (`dyn Trait`, `[Type]`, etc). If the type
45 /// in question is sized, use [`RwData::new`] instead.
46 pub fn new_unsized<SizedT: 'static>(data: Arc<RwLock<T>>) -> Self {
47 // It's 1 here so that any `RoState`s created from this will have
48 // `has_changed()` return `true` at least once, by copying the
49 // second value - 1.
50 Self {
51 data,
52 cur_state: Arc::new(AtomicUsize::new(1)),
53 read_state: AtomicUsize::new(1),
54 type_id: TypeId::of::<SizedT>(),
55 }
56 }
57
58 /// Blocking reference to the information
59 ///
60 /// Also makes it so that [`has_changed`] returns `false`.
61 ///
62 /// # Examples
63 ///
64 /// Since this is a blocking read, the thread will hault while the
65 /// data is being written to:
66 /// ```rust
67 /// # use std::{thread, time::{Duration, Instant}};
68 /// # use duat_core::data::{RoData, RwData};
69 /// let read_write_data = RwData::new("☹️");
70 /// let read_only_data = RoData::from(&read_write_data);
71 /// let instant = Instant::now();
72 /// thread::scope(|scope| {
73 /// scope.spawn(|| {
74 /// let mut read_write = read_write_data.write();
75 /// // Supposedly long computations.
76 /// thread::sleep(Duration::from_millis(150));
77 /// *read_write = "☺️";
78 /// });
79 ///
80 /// // Just making sure that the read happens slightly after the write.
81 /// thread::sleep(Duration::from_millis(10));
82 ///
83 /// let read_only = read_only_data.read();
84 /// let time_elapsed = Instant::now().duration_since(instant);
85 /// assert!(time_elapsed >= Duration::from_millis(100));
86 /// assert!(*read_only == "☺️");
87 /// });
88 /// ```
89 /// Note that other reads will **NOT** block reading in this way,
90 /// only writes:
91 /// ```rust
92 /// # use std::{thread, time::{Duration, Instant}};
93 /// # use duat_core::data::{RoData, RwData};
94 /// let read_write_data = RwData::new("☹️");
95 /// let read_only_data = RoData::from(&read_write_data);
96 /// let instant = Instant::now();
97 /// thread::scope(|scope| {
98 /// scope.spawn(|| {
99 /// let read_only = read_write_data.read();
100 /// // The thread hangs, but reading is still possible.
101 /// thread::sleep(Duration::from_millis(100));
102 /// });
103 ///
104 /// // Just making sure that this read happens slightly after the last one.
105 /// thread::sleep(Duration::from_millis(1));
106 ///
107 /// let read_only = read_only_data.read();
108 /// let time_elapsed = Instant::now().duration_since(instant);
109 /// assert!(time_elapsed < Duration::from_millis(100));
110 /// });
111 /// ```
112 /// [`has_changed`]: Self::has_changed
113 pub fn read(&self) -> RwLockReadGuard<'_, T> {
114 let cur_state = self.cur_state().load(Ordering::Acquire);
115 self.read_state().store(cur_state, Ordering::Release);
116 self.data()
117 }
118
119 /// Blocking inspection of the inner data
120 ///
121 /// Also makes it so that [`has_changed`] returns `false`.
122 ///
123 /// # Examples
124 ///
125 /// This method is useful if you want to scope the reading, or
126 /// need to drop the reference quickly, so it can be written to.
127 ///
128 /// You can do this:
129 /// ```rust
130 /// # use duat_core::data::{RoData, RwData};
131 /// # fn add_to_count(count: &mut usize) {}
132 /// # fn new_count() -> usize {
133 /// # 0
134 /// # }
135 /// let count = RwData::new(31);
136 /// let count_reader = RoData::from(&count);
137 ///
138 /// // The read write counterpart to `inspect`.
139 /// count.mutate(|count| {
140 /// *count += 5;
141 /// add_to_count(count)
142 /// });
143 ///
144 /// count_reader.inspect(|count| { /* reading operations */ });
145 ///
146 /// *count.write() = new_count();
147 /// ```
148 /// Instead of this:
149 /// ```rust
150 /// # use duat_core::data::{RoData, RwData};
151 /// # fn add_to_count(count: &mut usize) {}
152 /// # fn new_count() -> usize {
153 /// # 0
154 /// # }
155 /// let count = RwData::new(31);
156 /// let count_reader = RoData::from(&count);
157 ///
158 /// // The read write counterpart to `inspect`.
159 /// let mut count_write = count.write();
160 /// *count_write += 5;
161 /// add_to_count(&mut *count_write);
162 /// drop(count_write);
163 ///
164 /// let count_read = count_reader.read();
165 /// // reading operations
166 /// drop(count_read);
167 ///
168 /// *count.write() = new_count();
169 /// ```
170 /// Or this:
171 /// ```rust
172 /// # use duat_core::data::{RoData, RwData};
173 /// # fn add_to_count(count: &mut usize) {}
174 /// # fn new_count() -> usize {
175 /// # 0
176 /// # }
177 /// let count = RwData::new(31);
178 /// let count_reader = RoData::from(&count);
179 ///
180 /// // The read write counterpart to `inspect`.
181 /// {
182 /// let mut count = count.write();
183 /// *count += 5;
184 /// add_to_count(&mut count)
185 /// }
186 ///
187 /// {
188 /// let count = count.read();
189 /// // reading operations
190 /// }
191 ///
192 /// *count.write() = new_count();
193 /// ```
194 /// [`has_changed`]: Self::has_changed
195 pub fn inspect<U>(&self, f: impl FnOnce(&T) -> U) -> U {
196 let cur_state = self.cur_state().load(Ordering::Acquire);
197 self.read_state().store(cur_state, Ordering::Release);
198 f(&self.data())
199 }
200
201 /// Non blocking reference to the information
202 ///
203 /// If successful, also makes it so that [`has_changed`] returns
204 /// `false`.
205 ///
206 /// # Examples
207 ///
208 /// Unlike [`read`], can fail to return a reference to the
209 /// underlying data:
210 /// ```rust
211 /// # use std::{sync::TryLockError};
212 /// # use duat_core::data::RwData;
213 /// let new_data = RwData::new("hello 👋");
214 ///
215 /// let mut blocking_write = new_data.write();
216 /// *blocking_write = "bye 👋";
217 ///
218 /// let try_read = new_data.try_read();
219 /// assert!(matches!(try_read, None));
220 /// ```
221 ///
222 /// [`has_changed`]: Self::has_changed
223 /// [`read`]: Self::read
224 pub fn try_read(&self) -> Option<RwLockReadGuard<'_, T>> {
225 self.try_data().inspect(|_| {
226 let cur_state = self.cur_state().load(Ordering::Acquire);
227 self.read_state().store(cur_state, Ordering::Release);
228 })
229 }
230
231 /// Non blocking inspection of the inner data
232 ///
233 /// If successful, also makes it so that [`has_changed`] returns
234 /// `false`.
235 ///
236 /// # Examples
237 ///
238 /// Unlike [`inspect`], can fail to return a reference to the
239 /// underlying data:
240 /// ```rust
241 /// # use std::sync::TryLockError;
242 /// # use duat_core::data::RwData;
243 /// let new_data = RwData::new("hello 👋");
244 ///
245 /// let try_inspect = new_data.mutate(|blocking_mutate| {
246 /// *blocking_mutate = "bye 👋";
247 ///
248 /// new_data.try_inspect(|try_inspect| *try_inspect == "bye 👋")
249 /// });
250 ///
251 /// assert!(matches!(try_inspect, None));
252 /// ```
253 ///
254 /// [`has_changed`]: Self::has_changed
255 /// [`inspect`]: Self::inspect
256 pub fn try_inspect<U>(&self, f: impl FnOnce(&T) -> U) -> Option<U> {
257 self.try_data().map(|data| {
258 let cur_state = self.cur_state().load(Ordering::Acquire);
259 self.read_state().store(cur_state, Ordering::Release);
260 f(&data)
261 })
262 }
263
264 /// Whether or not it has changed since it was last read
265 ///
266 /// A "change" is defined as any time the methods [`write`],
267 /// [`mutate`], [`try_write`], or [`try_mutate`], are called on an
268 /// [`RwData`]. Once `has_changed` is called, the data will be
269 /// considered unchanged since the last `has_changed` call, for
270 /// that specific instance of a [`Data`].
271 ///
272 /// When first creating a [`Data`] type, `has_changed`
273 /// will return `false`;
274 ///
275 /// # Examples
276 /// ```rust
277 /// use duat_core::data::{RoData, RwData};
278 /// let new_data = RwData::new("Initial text");
279 /// assert!(!new_data.has_changed());
280 ///
281 /// let first_reader = RoData::from(&new_data);
282 ///
283 /// *new_data.write() = "Final text";
284 ///
285 /// let second_reader = RoData::from(&new_data);
286 ///
287 /// assert!(first_reader.has_changed());
288 /// assert!(!second_reader.has_changed());
289 /// ```
290 ///
291 /// [`write`]: RwData::write
292 /// [`mutate`]: RwData::mutate
293 /// [`try_write`]: RwData::try_write
294 /// [`try_mutate`]: RwData::try_mutate
295 pub fn has_changed(&self) -> bool {
296 let cur_state = self.cur_state().load(Ordering::Relaxed);
297 let read_state = self.read_state().swap(cur_state, Ordering::Relaxed);
298 cur_state > read_state
299 }
300
301 /// Returns `true` if both [`Data`]s point to the same
302 /// data.
303 ///
304 /// # Examples
305 /// ```rust
306 /// # use duat_core::data::{RwData};
307 /// let data_1 = RwData::new(false);
308 /// let data_1_clone = data_1.clone();
309 ///
310 /// let data_2 = RwData::new(true);
311 ///
312 /// assert!(data_1.ptr_eq(&data_1_clone));
313 /// assert!(!data_1.ptr_eq(&data_2));
314 /// ```
315 pub fn ptr_eq<U: ?Sized>(&self, other: &(impl Data<U> + ?Sized)) -> bool {
316 Arc::as_ptr(self.cur_state()) == Arc::as_ptr(other.cur_state())
317 }
318
319 /// Blocking mutable reference to the information
320 ///
321 /// Also makes it so that [`has_changed`] returns true for
322 /// `self` or any of its clones, be they [`RoData`] or
323 /// [`RwData`].
324 ///
325 /// # Safety
326 ///
327 /// Since this is a blocking function, you should be careful about
328 /// the prevention of deadlocks, one of the few unsafe aspects of
329 /// code that Rust doesn't prevent.
330 ///
331 /// As an example, this code will deadlock indefinitely:
332 /// ```no_run
333 /// # use std::{mem, thread, time::Duration};
334 /// # use duat_core::data::RwData;
335 /// let data_1 = RwData::new('😟');
336 /// let data_2 = RwData::new('😭');
337 ///
338 /// thread::scope(|scope| {
339 /// scope.spawn(|| {
340 /// let mut data_1 = data_1.write();
341 /// thread::sleep(Duration::from_millis(100));
342 /// let mut data_2 = data_2.write();
343 /// mem::swap(&mut data_1, &mut data_2);
344 /// });
345 ///
346 /// scope.spawn(|| {
347 /// let mut data_2 = data_2.write();
348 /// thread::sleep(Duration::from_millis(100));
349 /// let mut data_1 = data_1.write();
350 /// mem::swap(&mut data_1, &mut data_2);
351 /// });
352 /// });
353 /// ```
354 /// In general, try not to juggle multiple `&mut` handles to
355 /// [`RwData`]s. A good way of doing that is the
356 /// [`RwData::mutate`] method, which makes it very explicit when a
357 /// specific handle will be dropped, mitigating the possibility of
358 /// deadlocks.
359 ///
360 ///
361 /// [`has_changed`]: Data::has_changed
362 pub fn write(&self) -> ReadWriteGuard<T> {
363 let guard = self.data.write();
364 ReadWriteGuard { guard, cur_state: &self.cur_state }
365 }
366
367 /// Non Blocking mutable reference to the information
368 ///
369 /// Also makes it so that [`has_changed`] returns true for
370 /// `self` or any of its clones, be they [`RoData`] or
371 /// [`RwData`].
372 ///
373 /// # Safety
374 ///
375 /// Unlike [`RwData::write`], this method cannot cause deadlocks,
376 /// returning an [`Err`] instead.
377 /// ```
378 /// # use std::{mem, thread, time::Duration};
379 /// # use duat_core::data::RwData;
380 /// let data_1 = RwData::new('😀');
381 /// let data_2 = RwData::new('😁');
382 ///
383 /// thread::scope(|scope| {
384 /// scope.spawn(|| {
385 /// let mut data_1 = data_1.try_write();
386 /// thread::sleep(Duration::from_millis(100));
387 /// let mut data_2 = data_2.try_write();
388 /// if let (Some(mut data_1), Some(mut data_2)) = (data_1, data_2) {
389 /// mem::swap(&mut data_1, &mut data_2);
390 /// }
391 /// });
392 ///
393 /// scope.spawn(|| {
394 /// let mut data_2 = data_2.try_write();
395 /// thread::sleep(Duration::from_millis(100));
396 /// let mut data_1 = data_1.try_write();
397 /// if let (Some(mut data_1), Some(mut data_2)) = (data_1, data_2) {
398 /// mem::swap(&mut data_1, &mut data_2);
399 /// }
400 /// });
401 /// });
402 ///
403 /// // Two swaps will happen.
404 /// assert_eq!(*data_1.read(), '😀');
405 /// assert_eq!(*data_2.read(), '😁');
406 /// ```
407 /// The downside is that you may not want it to fail ever, in
408 /// which case, you should probably use [`RwData::write`].
409 ///
410 /// [`has_changed`]: Data::has_changed
411 pub fn try_write(&self) -> Option<ReadWriteGuard<'_, T>> {
412 self.data
413 .try_write()
414 .map(|guard| ReadWriteGuard { guard, cur_state: &self.cur_state })
415 }
416
417 /// Blocking mutation of the inner data
418 ///
419 /// Also makes it so that [`has_changed`] returns true for
420 /// `self` or any of its clones, be they [`RoData`] or
421 /// [`RwData`].
422 ///
423 /// # Safety
424 ///
425 /// This method "technically" has the same problems as
426 /// [`RwData::write`], where you can deadlock by calling it on
427 /// multiple instances of [`RwData`], but it makes this much more
428 /// explicit:
429 /// ```no_run
430 /// # use std::{mem, thread, time::Duration};
431 /// # use duat_core::data::RwData;
432 /// let data_1 = RwData::new('😟');
433 /// let data_2 = RwData::new('😭');
434 ///
435 /// thread::scope(|scope| {
436 /// scope.spawn(|| {
437 /// data_1.mutate(|data_1| {
438 /// thread::sleep(Duration::from_millis(100));
439 /// let mut data_2 = data_2.write();
440 /// mem::swap(data_1, &mut *data_2);
441 /// });
442 /// });
443 ///
444 /// scope.spawn(|| {
445 /// data_2.mutate(|data_2| {
446 /// thread::sleep(Duration::from_millis(100));
447 /// let mut data_1 = data_1.write();
448 /// mem::swap(&mut *data_1, data_2);
449 /// });
450 /// });
451 /// });
452 /// ```
453 /// Generally, you should favor this method for longer functions
454 /// in which the data is only needed for a short time.
455 ///
456 /// [`has_changed`]: Data::has_changed
457 pub fn mutate<R>(&self, f: impl FnOnce(&mut T) -> R) -> R {
458 f(&mut self.write().guard)
459 }
460
461 /// Non blocking mutation of the inner data
462 ///
463 /// Also makes it so that [`has_changed`] returns true for
464 /// `self` or any of its clones, be they [`RoData`] or
465 /// [`RwData`].
466 ///
467 /// # Safety
468 ///
469 /// Much like [`RwData::try_write`], this also can't deadlock,
470 /// failing instead. Generally, you should use this method only
471 /// when you are fine with not writing the data.
472 ///
473 /// [`has_changed`]: Data::has_changed
474 pub fn try_mutate<R>(&self, f: impl FnOnce(&mut T) -> R) -> Option<R> {
475 let res = self.try_write();
476 res.map(|mut data| f(&mut *data))
477 }
478
479 /// Blocking reference to the information
480 ///
481 /// Unlike [`read`], *DOES NOT* make it so
482 /// [`has_changed`] returns `false`.
483 ///
484 /// This method should only be used in very specific
485 /// circumstances, such as when multiple owners have nested
486 /// [`RwData`]s, thus referencing the same inner [`RwData`], in
487 /// a way that reading from one point would interfere in the
488 /// update detection of the other point.
489 ///
490 /// [`read`]: Self::read,
491 /// [`has_changed`]: Self::has_changed
492 pub(crate) fn raw_read(&self) -> RwLockReadGuard<'_, T> {
493 self.data()
494 }
495
496 /// Returns `true` if the data is of the concrete type `T`
497 ///
498 /// # Examples
499 ///
500 /// You may want this method if you're storing a list of
501 /// [`RwData<dyn Trait>`], and want to know, at runtime, what type
502 /// each element is:
503 /// ```rust
504 /// # use std::{any::Any, fmt::Display, sync::Arc};
505 /// # use duat_core::data::{RwData, RwLock};
506 /// let list: [RwData<dyn Display>; 3] = [
507 /// RwData::new_unsized::<String>(Arc::new(RwLock::new(String::from(
508 /// "I can show you the world",
509 /// )))),
510 /// RwData::new_unsized::<String>(Arc::new(RwLock::new(String::from(
511 /// "Shining, shimmering, splendid",
512 /// )))),
513 /// RwData::new_unsized::<char>(Arc::new(RwLock::new('🧞'))),
514 /// ];
515 ///
516 /// assert!(list[0].data_is::<String>());
517 /// assert!(list[1].data_is::<String>());
518 /// assert!(list[2].data_is::<char>());
519 /// ```
520 ///
521 /// [`RwData<dyn Trait>`]: RwData
522 pub fn data_is<U: ?Sized + 'static>(&self) -> bool {
523 self.type_id == TypeId::of::<U>()
524 }
525
526 /// Tries to downcast to a concrete type
527 ///
528 /// # Examples
529 ///
530 /// You may want this method if you're storing a list of
531 /// [`RwData<dyn Trait>`], and want to know, at runtime, what type
532 /// each element is:
533 /// ```rust
534 /// # use std::{fmt::Display, sync::Arc};
535 /// # use duat_core::data::{RwData, RwLock};
536 /// let list: [RwData<dyn Display>; 3] = [
537 /// RwData::new_unsized::<String>(Arc::new(RwLock::new(String::from(
538 /// "I can show you the world",
539 /// )))),
540 /// RwData::new_unsized::<String>(Arc::new(RwLock::new(String::from(
541 /// "Shining, shimmering, splendid",
542 /// )))),
543 /// RwData::new_unsized::<char>(Arc::new(RwLock::new('🧞'))),
544 /// ];
545 ///
546 /// let maybe_char = list[2].clone().try_downcast::<char>();
547 /// assert!(maybe_char.is_some());
548 /// *maybe_char.unwrap().write() = '👳';
549 ///
550 /// let maybe_string = list[0].clone().try_downcast::<char>();
551 /// assert!(maybe_string.is_none());
552 /// ```
553 /// If you don't need to write to the data, consider using
554 /// [`RwData::inspect_as`]. If you only need to know if the type
555 /// matches, consider using [`RwData::data_is`].
556 ///
557 /// [`RwData<dyn Trait>`]: RwData
558 pub fn try_downcast<U: 'static>(&self) -> Option<RwData<U>> {
559 if self.data_is::<U>() {
560 let Self { data, cur_state, read_state, .. } = self.clone();
561 let ptr = Arc::into_raw(data);
562 let data = unsafe { Arc::from_raw(ptr.cast()) };
563 Some(RwData {
564 data,
565 cur_state,
566 read_state,
567 type_id: self.type_id,
568 })
569 } else {
570 None
571 }
572 }
573
574 /// Blocking inspection of the inner data
575 ///
576 /// # Examples
577 ///
578 /// You may want this method if you're storing a list of
579 /// [`RwData<dyn Trait>`], and want to know, at runtime, what type
580 /// each element is:
581 /// ```rust
582 /// # use std::{any::Any, fmt::Display, sync::Arc};
583 /// # use duat_core::data::{RwData, RwLock};
584 /// let list: [RwData<dyn Display>; 3] = [
585 /// RwData::new_unsized::<String>(Arc::new(RwLock::new(String::from(
586 /// "I can show you the world",
587 /// )))),
588 /// RwData::new_unsized::<String>(Arc::new(RwLock::new(String::from(
589 /// "Shining, shimmering, splendid",
590 /// )))),
591 /// RwData::new_unsized::<char>(Arc::new(RwLock::new('🧞'))),
592 /// ];
593 ///
594 /// assert!(matches!(
595 /// list[2].inspect_as::<char, usize>(|char| char.len_utf8()),
596 /// Some(4)
597 /// ));
598 /// assert!(matches!(
599 /// list[1].inspect_as::<char, char>(|char| char.to_ascii_uppercase()),
600 /// None
601 /// ));
602 /// ```
603 ///
604 /// [`RwData<dyn Trait>`]: RwData
605 pub fn inspect_as<U: 'static, R>(&self, f: impl FnOnce(&U) -> R) -> Option<R> {
606 (self.data_is::<U>()).then(|| {
607 let ptr = Arc::as_ptr(&self.data);
608 let cast = unsafe { ptr.cast::<RwLock<U>>().as_ref().unwrap() };
609
610 self.read_state
611 .store(self.cur_state.load(Ordering::Acquire), Ordering::Release);
612
613 f(&cast.read())
614 })
615 }
616
617 pub fn mutate_as<U: 'static, R>(&self, f: impl FnOnce(&mut U) -> R) -> Option<R> {
618 (self.data_is::<U>()).then(|| {
619 let ptr = Arc::as_ptr(&self.data);
620 let cast = unsafe { ptr.cast::<RwLock<U>>().as_ref().unwrap() };
621
622 self.read_state
623 .store(self.cur_state.load(Ordering::Acquire), Ordering::Release);
624
625 let mut guard = cast.write();
626 f(&mut guard)
627 })
628 }
629
630 pub(crate) fn raw_write(&self) -> RwLockWriteGuard<'_, T> {
631 self.data.write()
632 }
633}
634
635impl<T: ?Sized + std::fmt::Debug> std::fmt::Debug for RwData<T> {
636 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
637 std::fmt::Debug::fmt(&*self.data.read(), f)
638 }
639}
640
641impl<T: ?Sized> Clone for RwData<T> {
642 fn clone(&self) -> Self {
643 Self {
644 data: self.data.clone(),
645 cur_state: self.cur_state.clone(),
646 read_state: AtomicUsize::new(self.cur_state.load(Ordering::Relaxed) - 1),
647 type_id: self.type_id,
648 }
649 }
650}
651
652impl<T: Default> Default for RwData<T> {
653 fn default() -> Self {
654 Self {
655 data: Arc::new(RwLock::new(T::default())),
656 cur_state: Arc::new(AtomicUsize::new(1)),
657 read_state: AtomicUsize::new(1),
658 type_id: TypeId::of::<T>(),
659 }
660 }
661}
662
663impl<T: ?Sized> InnerData<T> for RwData<T> {
664 fn data(&self) -> RwLockReadGuard<'_, T> {
665 self.data.read()
666 }
667
668 fn try_data(&self) -> Option<RwLockReadGuard<'_, T>> {
669 self.data.try_read()
670 }
671
672 fn cur_state(&self) -> &Arc<AtomicUsize> {
673 &self.cur_state
674 }
675
676 fn read_state(&self) -> &AtomicUsize {
677 &self.read_state
678 }
679}
680
681impl<T: ?Sized> Data<T> for RwData<T> {
682 fn to_ro(&self) -> super::RoData<T> {
683 RoData::from(self)
684 }
685
686 fn has_changed(&self) -> bool {
687 self.has_changed()
688 }
689}
690
691pub struct ReadWriteGuard<'a, T: ?Sized> {
692 guard: RwLockWriteGuard<'a, T>,
693 cur_state: &'a Arc<AtomicUsize>,
694}
695
696impl<T: ?Sized> std::ops::Deref for ReadWriteGuard<'_, T> {
697 type Target = T;
698
699 fn deref(&self) -> &Self::Target {
700 &self.guard
701 }
702}
703
704impl<T: ?Sized> std::ops::DerefMut for ReadWriteGuard<'_, T> {
705 fn deref_mut(&mut self) -> &mut Self::Target {
706 &mut self.guard
707 }
708}
709
710impl<T: ?Sized> Drop for ReadWriteGuard<'_, T> {
711 fn drop(&mut self) {
712 self.cur_state.fetch_add(1, Ordering::Release);
713 }
714}