intuicio_data/
shared.rs

1use std::{
2    cell::{Ref, RefCell, RefMut},
3    rc::Rc,
4    sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard},
5};
6
7#[derive(Default)]
8pub struct Shared<T> {
9    data: Rc<RefCell<T>>,
10}
11
12impl<T> Clone for Shared<T> {
13    fn clone(&self) -> Self {
14        Self {
15            data: self.data.clone(),
16        }
17    }
18}
19
20impl<T> Shared<T> {
21    pub fn new(data: T) -> Self {
22        Self {
23            data: Rc::new(RefCell::new(data)),
24        }
25    }
26
27    pub fn try_consume(self) -> Result<T, Self> {
28        match Rc::try_unwrap(self.data) {
29            Ok(data) => Ok(data.into_inner()),
30            Err(data) => Err(Self { data }),
31        }
32    }
33
34    pub fn read(&self) -> Option<Ref<T>> {
35        self.data.try_borrow().ok()
36    }
37
38    pub fn write(&self) -> Option<RefMut<T>> {
39        self.data.try_borrow_mut().ok()
40    }
41
42    pub fn swap(&self, data: T) -> Option<T> {
43        let mut value = self.data.try_borrow_mut().ok()?;
44        Some(std::mem::replace(&mut value, data))
45    }
46
47    pub fn references_count(&self) -> usize {
48        Rc::strong_count(&self.data)
49    }
50
51    pub fn does_share_reference(&self, other: &Self) -> bool {
52        Rc::ptr_eq(&self.data, &other.data)
53    }
54}
55
56#[derive(Default)]
57pub struct AsyncShared<T> {
58    data: Arc<RwLock<T>>,
59}
60
61impl<T> Clone for AsyncShared<T> {
62    fn clone(&self) -> Self {
63        Self {
64            data: self.data.clone(),
65        }
66    }
67}
68
69impl<T> AsyncShared<T> {
70    pub fn new(data: T) -> Self {
71        Self {
72            data: Arc::new(RwLock::new(data)),
73        }
74    }
75
76    pub fn try_consume(self) -> Result<T, Self> {
77        match Arc::try_unwrap(self.data) {
78            Ok(data) => Ok(data.into_inner().unwrap()),
79            Err(data) => Err(Self { data }),
80        }
81    }
82
83    pub fn read(&self) -> Option<RwLockReadGuard<T>> {
84        self.data.read().ok()
85    }
86
87    pub fn write(&self) -> Option<RwLockWriteGuard<T>> {
88        self.data.write().ok()
89    }
90
91    pub fn swap(&self, data: T) -> Option<T> {
92        let mut value = self.data.write().ok()?;
93        Some(std::mem::replace(&mut value, data))
94    }
95
96    pub fn references_count(&self) -> usize {
97        Arc::strong_count(&self.data)
98    }
99
100    pub fn does_share_reference(&self, other: &Self) -> bool {
101        Arc::ptr_eq(&self.data, &other.data)
102    }
103}
104
105#[cfg(test)]
106mod tests {
107    use super::Shared;
108
109    #[test]
110    fn test_shared() {
111        let a = Shared::new(42);
112        assert_eq!(a.references_count(), 1);
113        assert_eq!(*a.read().unwrap(), 42);
114        let b = a.clone();
115        assert_eq!(a.references_count(), 2);
116        assert_eq!(b.references_count(), 2);
117        assert_eq!(*b.read().unwrap(), 42);
118        *b.write().unwrap() = 10;
119        assert_eq!(*a.read().unwrap(), 10);
120        assert_eq!(*b.read().unwrap(), 10);
121        assert!(b.try_consume().is_err());
122        assert_eq!(a.try_consume().ok().unwrap(), 10);
123    }
124}