voluntary_servitude/
node.rs

1//! [`VoluntaryServitude`] node implementation
2//!
3//! [`VoluntaryServitude`]: ./struct.VoluntaryServitude.html
4
5use crate::prelude::*;
6use std::fmt::{self, Debug, Formatter};
7use std::sync::atomic::Ordering;
8
9/// One [`VoluntaryServitude`] element
10///
11/// [`VoluntaryServitude`]: ./struct.VoluntaryServitude.html
12pub struct Node<T> {
13    /// Inner value
14    value: T,
15    /// Next node in chain
16    next: FillOnceAtomicOption<Node<T>>,
17}
18
19impl<T> Node<T> {
20    /// Returns reference to inner value
21    #[inline]
22    pub fn value(&self) -> &T {
23        trace!("value() = {:p}", &self.value);
24        &self.value
25    }
26
27    /// Creates new node with inner value
28    #[inline]
29    pub fn new(value: T) -> Self {
30        trace!("new()");
31        let next = FillOnceAtomicOption::default();
32        Self { value, next }
33    }
34
35    /// Gets next pointer
36    #[inline]
37    pub fn next(&self) -> Option<&Self> {
38        trace!("next()");
39        self.next.get_ref(Ordering::Relaxed)
40    }
41
42    /// Inserts next as if there was None
43    #[inline]
44    pub fn try_store_next(&self, node: Box<Self>) -> Result<(), NotEmpty> {
45        trace!("try_store_next({:p})", node);
46        self.next.try_store(node, Ordering::Relaxed)
47    }
48}
49
50/// Default Drop is recursive and causes a stackoverflow easily
51impl<T> Drop for Node<T> {
52    #[inline]
53    fn drop(&mut self) {
54        debug!("Drop nodes");
55        let mut node = self.next.take(Ordering::Relaxed);
56        while let Some(mut n) = node {
57            node = n.next.take(Ordering::Relaxed);
58        }
59    }
60}
61
62impl<T: Debug> Debug for Node<T> {
63    #[inline]
64    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
65        f.debug_struct("Node")
66            .field("value", &self.value)
67            .field("next", &self.next.get_ref(Ordering::Relaxed))
68            .finish()
69    }
70}