lockfree/
removable.rs

1use std::{
2    fmt,
3    mem::{replace, uninitialized, ManuallyDrop},
4    sync::atomic::{
5        AtomicBool,
6        Ordering::{self, *},
7    },
8};
9
10/// A shared removable value. You can only take values from this type (no
11/// insertion allowed). No extra allocation is necessary. It may be useful for
12/// things like shared `thread::JoinHandle`s.
13pub struct Removable<T> {
14    item: ManuallyDrop<T>,
15    present: AtomicBool,
16}
17
18impl<T> Removable<T> {
19    /// Creates a removable item with the passed argument as a present value.
20    pub fn new(val: T) -> Self {
21        Self { item: ManuallyDrop::new(val), present: AtomicBool::new(true) }
22    }
23
24    /// Creates a removable item with no present value.
25    pub fn empty() -> Self {
26        Self {
27            // This is safe because we will only read from the item if present
28            // is true. Present will only be true if we write to it.
29            item: ManuallyDrop::new(unsafe { uninitialized() }),
30            present: AtomicBool::new(false),
31        }
32    }
33
34    /// Replaces the stored value with a given one and returns the old value.
35    /// Requires a mutable reference since the type of the value might not be
36    /// atomic.
37    pub fn replace(&mut self, val: Option<T>) -> Option<T> {
38        let present = self.present.get_mut();
39
40        match val {
41            Some(val) => {
42                if *present {
43                    Some(replace(&mut *self.item, val))
44                } else {
45                    // Safe because we get the pointer from a valid reference
46                    // and present will only be false if item is uninitialized.
47                    *present = true;
48                    unsafe { (&mut *self.item as *mut T).write(val) };
49                    None
50                }
51            },
52
53            None if *present => {
54                // Safe because we get the pointer from a valid reference
55                // and present will only be false if item is uninitialized.
56                *present = false;
57                Some(unsafe { (&*self.item as *const T).read() })
58            },
59
60            None => None,
61        }
62    }
63
64    /// Tries to get a mutable reference to the stored value. If the value was
65    /// not present, `None` is returned.
66    pub fn get_mut(&mut self) -> Option<&mut T> {
67        if *self.present.get_mut() {
68            Some(&mut *self.item)
69        } else {
70            None
71        }
72    }
73
74    /// Tests if the stored value is present. Note that there are no guarantees
75    /// that `take` will be successful if this method returns `true` because
76    /// some other thread could take the value meanwhile.
77    pub fn is_present(&self, ordering: Ordering) -> bool {
78        self.present.load(ordering)
79    }
80
81    /// Tries to take the value. If no value was present in first place, `None`
82    /// is returned. In terms of memory ordering, `AcqRel` should be enough.
83    pub fn take(&self, ordering: Ordering) -> Option<T> {
84        if self.present.swap(false, ordering) {
85            // Safe because if present was true, the memory was initialized. All
86            // other reads won't happen because we set present to false.
87            Some(unsafe { (&*self.item as *const T).read() })
88        } else {
89            None
90        }
91    }
92}
93
94impl<T> fmt::Debug for Removable<T> {
95    fn fmt(&self, fmtr: &mut fmt::Formatter) -> fmt::Result {
96        write!(
97            fmtr,
98            "Removable {} present: {:?} {}",
99            '{',
100            self.is_present(Relaxed),
101            '}'
102        )
103    }
104}
105
106impl<T> Default for Removable<T> {
107    fn default() -> Self {
108        Self::empty()
109    }
110}
111
112impl<T> Drop for Removable<T> {
113    fn drop(&mut self) {
114        if *self.present.get_mut() {
115            // Safe because present will only be true when the memory is
116            // initialized. And now we are at drop.
117            unsafe { ManuallyDrop::drop(&mut self.item) }
118        }
119    }
120}
121
122impl<T> From<Option<T>> for Removable<T> {
123    fn from(opt: Option<T>) -> Self {
124        match opt {
125            Some(item) => Self::new(item),
126            None => Self::empty(),
127        }
128    }
129}
130
131unsafe impl<T> Send for Removable<T> where T: Send {}
132unsafe impl<T> Sync for Removable<T> where T: Send {}