lock_freedom/
removable.rs

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