     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89

    use std::sync::atomic::Ordering::{Acquire, Release, Relaxed};
    use std::ptr;

    use mem::epoch::{self, Atomic, Owned};

    /// Treiber's lock-free stack.
    ///
    /// Usable with any number of producers and consumers.
    pub struct TreiberStack<T> {
        head: Atomic<Node<T>>,
    }

    struct Node<T> {
        data: T,
        next: Atomic<Node<T>>,
    }

    impl<T> TreiberStack<T> {
        /// Create a new, empty stack.
        pub fn new() -> TreiberStack<T> {
            TreiberStack {
                head: Atomic::null()
            }
        }

        /// Push `t` on top of the stack.
        pub fn push(&self, t: T) {
            let mut n = Owned::new(Node {
                data: t,
                next: Atomic::null()
            });
            let guard = epoch::pin();
            loop {
                let head = self.head.load(Relaxed, &guard);
                n.next.store_shared(head, Relaxed);
                match self.head.cas_and_ref(head, n, Release, &guard) {
                    Ok(_) => break,
                    Err(owned) => n = owned,
                }
            }
        }

        /// Attempt to pop the top element of the stack.
        ///
        /// Returns `None` if the stack is observed to be empty.
        pub fn pop(&self) -> Option<T> {
            let guard = epoch::pin();
            loop {
                match self.head.load(Acquire, &guard) {
                    Some(head) => {
                        let next = head.next.load(Relaxed, &guard);
                        if self.head.cas_shared(Some(head), next, Release) {
                            unsafe {
                                guard.unlinked(head);
                                return Some(ptr::read(&(*head).data))
                            }
                        }
                    }
                    None => return None
                }
            }
        }

        /// Check if this queue is empty.
        pub fn is_empty(&self) -> bool {
            let guard = epoch::pin();
            self.head.load(Acquire, &guard).is_none()
        }
    }

    #[cfg(test)]
    mod test {
        use super::*;

        #[test]
        fn is_empty() {
            let q: TreiberStack<i64> = TreiberStack::new();
            assert!(q.is_empty());
            q.push(20);
            q.push(20);
            assert!(!q.is_empty());
            assert!(!q.is_empty());
            assert!(q.pop().is_some());
            assert!(q.pop().is_some());
            assert!(q.is_empty());
            q.push(25);
            assert!(!q.is_empty());
        }
    }

# Help

## Keyboard Shortcuts

?
  Show this help dialog
S
  Focus the search field
⇤
  Move up in search results
⇥
  Move down in search results
⏎
  Go to active search result

## Search Tricks

Prefix searches with a type followed by a colon (e.g. `fn:`) to restrict the search to a given type.

Accepted types are: `fn`, `mod`, `struct`, `enum`, `trait`, `type`, `macro`, and `const`.

Search functions by type signature (e.g. `vec -> usize` or `* -> vec`)