rain_lang/graph/
node.rs

1/*!
2Nodes of the `rain` graph
3*/
4use std::ops::{Deref, DerefMut};
5use std::borrow::Cow;
6use std::convert::Infallible;
7use std::sync::{Arc, Weak};
8use std::fmt::{self, Debug, Display, Formatter};
9use std::hash::{Hash, Hasher};
10use either::Either;
11use parking_lot::{RwLock, RwLockReadGuard, RwLockUpgradableReadGuard, RwLockWriteGuard};
12use super::cons::CacheAcceptor;
13
14/// A node in a `rain` graph
15#[derive(Debug)]
16pub struct Node<T: ?Sized> {
17    /// A reference-counted pointer to the data held in this node
18    data: Arc<RwLock<T>>
19}
20
21impl<T: ?Sized> Node<T> {
22    /// Read the data associated with a `rain` node
23    pub fn data(&self) -> View<RwLockReadGuard<T>> { View::new(self.data.read()) }
24    /// Try to read the data associated with a `rain` node.
25    /// Return `None` if the data is currently unavailable to read, i.e. there is a write occuring
26    /// ```rust
27    /// use std::ops::Deref;
28    /// use rain_lang::graph::node::{Node, Data};
29    /// let node = Node::new(Data(true));
30    /// {
31    ///     let read = node.data();
32    ///     assert_eq!(read.deref(), &Data(true));
33    ///     let try_read = node.try_data().expect("Multiple reads are allowed!");
34    ///     assert_eq!(try_read.deref(), &Data(true));
35    /// }
36    /// let mut write = node.data_mut();
37    /// *write = Data(false);
38    /// assert_eq!(write.deref(), &Data(false));
39    /// assert!(node.try_data().is_none(), "Concurrent reads and writes are not allowed!");
40    /// ```
41    pub fn try_data(&self) -> Option<View<RwLockReadGuard<T>>> {
42        self.data.try_read().map(View::new)
43    }
44    /// Mutably get the data associated with a `rain` node. Note mutation is limited to
45    /// operations which will not corrupt the `rain` graph (e.g. adding dependencies)
46    pub fn data_mut(&self) -> View<RwLockWriteGuard<T>> { View::new(self.data.write()) }
47    /// Try to mutably get the data associated with a `rain` node
48    /// Return `None` if the data is currently unavailable to write
49    /// ```rust
50    /// use std::ops::Deref;
51    /// use rain_lang::graph::node::{Node, Data};
52    /// let node = Node::new(Data(true));
53    /// {
54    ///     let mut try_write = node.try_data_mut().expect("Valid write");
55    ///     *try_write = Data(false);
56    /// }
57    /// let read = node.data();
58    /// assert_eq!(read.deref(), &Data(false));
59    /// let try_read = node.try_data().expect("Multiple reads are allowed!");
60    /// assert_eq!(try_read.deref(), &Data(false));
61    /// assert!(node.try_data_mut().is_none(), "Concurrent reads and writes are not allowed!");
62    /// ```
63    pub fn try_data_mut(&self) -> Option<View<RwLockWriteGuard<T>>> {
64        self.data.try_write().map(View::new)
65    }
66    /// Downgrade this node to a weak handle
67    pub fn downgrade(&self) -> WeakNode<T> { WeakNode { data: Arc::downgrade(&self.data) } }
68}
69
70impl<T: ?Sized> Clone for Node<T> {
71    #[inline(always)] fn clone(&self) -> Node<T> { Node { data: self.data.clone() } }
72}
73
74impl<T: ?Sized> PartialEq for Node<T> {
75    #[inline] fn eq(&self, other: &Node<T>) -> bool { Arc::ptr_eq(&self.data, &other.data) }
76}
77
78impl<T: ?Sized> Eq for Node<T> {}
79
80impl<T: ?Sized> Hash for Node<T> {
81    #[inline] fn hash<H: Hasher>(&self, hasher: &mut H) {
82        (self.data.deref() as *const RwLock<_>).hash(hasher)
83    }
84}
85
86/// A node which has not yet been backlinked
87#[derive(Debug, Clone)]
88pub struct NotBacklinked<T>(Node<T>);
89
90impl<T: NodeData> NotBacklinked<T> {
91    /// Backlink a given node
92    pub fn backlink(self) -> Result<Node<T>, T::Error> {
93        {
94            let mut data = self.0.data.write();
95            data.backlink(Backlink(&self.0))?;
96        }
97        Ok(self.0)
98    }
99}
100
101/// A backlink to a node
102#[derive(Debug, Clone)]
103pub struct Backlink<'a, T>(&'a Node<T>);
104
105impl<T> Deref for Backlink<'_, T> {
106    type Target = Node<T>;
107    #[inline(always)] fn deref(&self) -> &Node<T> { self.0 }
108}
109
110/// A trait implemented by items which can be placed into a node, but may require a node backlink
111pub trait NodeData: Sized {
112    /// A possible error in placing an item into a node *or* deduplicating
113    type Error;
114    /// An acceptor for cache entries
115    type CacheAcceptor: CacheAcceptor<Self>;
116    /// Backlink this data to the given node.
117    /// **Warning:**
118    /// *Any* attempt to read the data of `backlink` in this function will lead to *deadlock*!
119    /// Backlinking should *not* create new nodes if dedup obtains a lock on the cache table!
120    fn backlink(&mut self, _backlink: Backlink<Self>) -> Result<(), Self::Error> { Ok(()) }
121    /// Attempt to deduplicate this `NodeData`, either succeeding or returning a cache entry
122    /// to place the newly created node in *should backlinking succeed*.
123    fn dedup(&mut self) -> Either<Node<Self>, Self::CacheAcceptor>;
124}
125
126/// A view into a node's data, allowing limited mutation
127#[derive(Debug, PartialEq)]
128pub struct View<R>(pub(crate) R);
129
130impl<R> Deref for View<R> where R: Deref {
131    type Target = R::Target;
132    fn deref(&self) -> &R::Target { self.0.deref() }
133}
134
135impl<R> View<R> where R: Deref {
136    /// Create a new value view
137    pub fn new(r: R) -> View<R> { View(r) }
138}
139
140impl<'a, T> View<RwLockWriteGuard<'a, T>> {
141    /// Downgrade this write view to a read view
142    pub fn downgrade(self) -> View<RwLockReadGuard<'a, T>> {
143        View::new(RwLockWriteGuard::downgrade(self.0))
144    }
145    /// Downgrade this write view to an upgradeable read view
146    pub fn downgrade_to_upgradeable(self) -> View<RwLockUpgradableReadGuard<'a, T>> {
147        View::new(RwLockWriteGuard::downgrade_to_upgradable(self.0))
148    }
149}
150
151impl<'a, T> View<RwLockUpgradableReadGuard<'a, T>> {
152    /// Upgrade this read guard
153    pub fn upgrade(self) -> View<RwLockWriteGuard<'a, T>> {
154        View::new(RwLockUpgradableReadGuard::upgrade(self.0))
155    }
156    /// Try to upgrade this read guard
157    pub fn try_upgrade(self) -> Result<View<RwLockWriteGuard<'a, T>>, Self> {
158        match RwLockUpgradableReadGuard::try_upgrade(self.0) {
159            Ok(up) => Ok(View::new(up)),
160            Err(s) => Err(View::new(s))
161        }
162    }
163}
164
165impl<T: NodeData> Node<T> {
166    /// Create a new, non-backlinked node from given data, *without deduplication!*
167    fn not_backlinked(data: T) -> NotBacklinked<T> {
168        NotBacklinked(Node { data : Arc::new(RwLock::new(data)) })
169    }
170    /// Try to create a new node from given data, which *can* fail
171    pub fn try_new(mut data: T) -> Result<Node<T>, T::Error> {
172        match data.dedup() {
173            Either::Left(node) => Ok(node),
174            Either::Right(acceptor) => {
175                let node = Node::not_backlinked(data).backlink()?;
176                acceptor.accept(node.downgrade());
177                Ok(node)
178            }
179        }
180    }
181}
182
183impl<T: NodeData<Error=Infallible>> Node<T> {
184    /// Try to create a new node from given data, which cannot fail
185    pub fn new(data: T) -> Node<T> {
186        Node::try_new(data).unwrap_or_else(|err| match err {})
187    }
188}
189
190impl<T: Display> Display for Node<T> {
191    fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
192        write!(fmt, "{}", self.data().deref())
193    }
194}
195
196/// A weak handle on a node in a `rain` graph
197#[derive(Debug)]
198pub struct WeakNode<T: ?Sized> {
199    /// A weak reference-counted pointer to the data held in this node
200    data: Weak<RwLock<T>>
201}
202
203impl<T: ?Sized> Clone for WeakNode<T> {
204    #[inline(always)] fn clone(&self) -> WeakNode<T> { WeakNode { data: self.data.clone() } }
205}
206
207impl<T> Default for WeakNode<T> {
208    #[inline(always)] fn default() -> WeakNode<T> { WeakNode { data: Weak::default() } }
209}
210
211impl<T: ?Sized> WeakNode<T> {
212    /// Attempt to upgrade this node to a strong handle
213    pub fn upgrade(&self) -> Option<Node<T>> { self.data.upgrade().map(|data| Node { data }) }
214}
215
216impl<T: ?Sized> PartialEq for WeakNode<T> {
217    fn eq(&self, other: &WeakNode<T>) -> bool { self.data.ptr_eq(&other.data) }
218}
219
220impl<T: ?Sized> Eq for WeakNode<T> {}
221
222impl<T> Hash for WeakNode<T> {
223    #[inline] fn hash<H: Hasher>(&self, hasher: &mut H) {
224        self.data.as_ptr().hash(hasher)
225    }
226}
227
228impl<T> WeakNode<T> {
229    /// Check whether this weak node is null
230    pub fn is_null(&self) -> bool { self == &WeakNode::default() }
231}
232
233impl<T> WeakNode<T> {
234    /// Create a new, empty weak node
235    pub fn new() -> WeakNode<T> { WeakNode { data: Weak::default() } }
236    /// Check whether this weak node points to the same allocation as another
237    /// Returns false if either pointer points to no allocation.
238    pub fn alloc_eq(&self, other: &WeakNode<T>) -> bool {
239        !self.data.ptr_eq(&Weak::new()) && self == other
240    }
241}
242
243/// A trait implemented by values which have a weak node address associated with them
244pub trait HasThis<T=Self> {
245    /// Get a `Cow` of the weak node address associated with this value.
246    /// May be `null` if there is none.
247    fn this(&self) -> Cow<WeakNode<T>>;
248}
249
250impl<T> HasThis<T> for WeakNode<T> {
251    fn this(&self) -> Cow<WeakNode<T>> { Cow::Borrowed(&self) }
252}
253
254/// A trait implemented by values which have a strong node address associated with them
255pub trait HasAddr<T=Self> {
256    /// Get a `Cow` of the strong node address associated with this value
257    fn addr(&self) -> Cow<Node<T>>;
258}
259
260impl<T> HasAddr<T> for Node<T> {
261    #[inline(always)] fn addr(&self) -> Cow<Node<T>> { Cow::Borrowed(&self) }
262}
263
264impl<T> HasThis<T> for Node<T> {
265    #[inline(always)] fn this(&self) -> Cow<WeakNode<T>> { Cow::Owned(self.downgrade()) }
266}
267
268/// Transforms an iterator over `&Node`s into an iterator over `WeakNode`s
269#[derive(Debug, Copy, Clone, Eq, PartialEq)]
270pub struct ToWeak<I>(pub I);
271
272impl<'a, T: 'a, I> Iterator for ToWeak<I> where I: Iterator<Item=&'a Node<T>> {
273    type Item = WeakNode<T>;
274    fn next(&mut self) -> Option<WeakNode<T>> { self.0.next().map(Node::downgrade) }
275    fn size_hint(&self) -> (usize, Option<usize>) { self.0.size_hint() }
276    fn count(self) -> usize { self.0.count() }
277    fn last(self) -> Option<WeakNode<T>> { self.0.last().map(Node::downgrade) }
278    fn nth(&mut self, n: usize) -> Option<WeakNode<T>> { self.0.nth(n).map(Node::downgrade) }
279}
280
281impl<'a, T: 'a, I> ExactSizeIterator for ToWeak<I> where I: ExactSizeIterator<Item=&'a Node<T>> {
282    fn len(&self) -> usize { self.0.len() }
283}
284
285impl<'a, T: 'a, I> DoubleEndedIterator for ToWeak<I> where I: DoubleEndedIterator<Item=&'a Node<T>>
286{
287    fn next_back(&mut self) -> Option<WeakNode<T>> { self.0.next_back().map(Node::downgrade) }
288}
289
290/// Simple data inside a node
291#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Default)]
292pub struct Data<T>(pub T);
293
294impl<T> Deref for Data<T> {
295    type Target = T;
296    fn deref(&self) -> &T { &self.0 }
297}
298
299impl<T> DerefMut for Data<T> {
300    fn deref_mut(&mut self) -> &mut T { &mut self.0 }
301}
302
303impl<T> NodeData for Data<T> {
304    type Error = Infallible;
305    type CacheAcceptor = ();
306    fn dedup(&mut self) -> Either<Node<Data<T>>, ()> { Either::Right(()) }
307}
308
309impl<R, T> DerefMut for View<R> where R: DerefMut<Target=Data<T>> {
310    fn deref_mut(&mut self) -> &mut Data<T> { self.0.deref_mut() }
311}