mirror_common/
atomic.rs

1use std::{
2    ptr::null_mut,
3    sync::atomic::{
4        AtomicBool, AtomicI16, AtomicI32, AtomicI64, AtomicI8, AtomicIsize, AtomicPtr, AtomicU16,
5        AtomicU32, AtomicU64, AtomicU8, AtomicUsize, Ordering,
6    },
7};
8
9pub trait EasyAtomic {
10    type Item;
11
12    /// Update atomic value.
13    ///
14    /// ```no_run
15    /// use std::sync::atomic::{AtomicU8, Ordering};
16    /// use sync::atomic::EasyAtomic;
17    ///
18    /// impl EsayAtomic for AtomicU8 {
19    ///     type Item = u8;
20    ///
21    ///     fn get(&self) -> Self::Item {
22    ///         self.load(Ordering::Relaxed)
23    ///     }
24    ///
25    ///     fn update(&self, value: Self::Item) -> Self::Item {
26    ///         self.swap(value, Ordering::Relaxed)
27    ///     }
28    /// }
29    /// ````
30    fn update(&self, value: Self::Item) -> Self::Item;
31
32    /// Get atomic value.
33    ///
34    /// ```no_run
35    /// use std::sync::atomic::{AtomicU8, Ordering};
36    /// use sync::atomic::EasyAtomic;
37    ///
38    /// impl EsayAtomic for AtomicU8 {
39    ///     type Item = u8;
40    ///
41    ///     fn get(&self) -> Self::Item {
42    ///         self.load(Ordering::Relaxed)
43    ///     }
44    ///
45    ///     fn update(&self, value: Self::Item) -> Self::Item {
46    ///         self.swap(value, Ordering::Relaxed)
47    ///     }
48    /// }
49    /// ````
50    fn get(&self) -> Self::Item;
51}
52
53macro_rules! easy_atomic {
54    ($typed:ty, $item:ty) => {
55        impl EasyAtomic for $typed {
56            type Item = $item;
57
58            fn get(&self) -> Self::Item {
59                self.load(Ordering::Relaxed)
60            }
61
62            fn update(&self, value: Self::Item) -> Self::Item {
63                self.swap(value, Ordering::Relaxed)
64            }
65        }
66    };
67}
68
69easy_atomic!(AtomicI8, i8);
70easy_atomic!(AtomicU8, u8);
71easy_atomic!(AtomicI16, i16);
72easy_atomic!(AtomicU16, u16);
73easy_atomic!(AtomicI32, i32);
74easy_atomic!(AtomicU32, u32);
75easy_atomic!(AtomicI64, i64);
76easy_atomic!(AtomicU64, u64);
77easy_atomic!(AtomicBool, bool);
78easy_atomic!(AtomicIsize, isize);
79easy_atomic!(AtomicUsize, usize);
80
81/// Atomized Option type.
82pub struct AtomicOption<T>(AtomicPtr<T>);
83
84impl<T> Default for AtomicOption<T> {
85    fn default() -> Self {
86        Self::new(None)
87    }
88}
89
90impl<T> AtomicOption<T> {
91    pub fn new(value: Option<T>) -> Self {
92        Self(AtomicPtr::new(
93            value
94                .map(|v| Box::into_raw(Box::new(v)))
95                .unwrap_or(null_mut()),
96        ))
97    }
98
99    /// # Example
100    ///
101    /// ```no_run
102    /// use sync::atomic::AtomicOption;
103    ///
104    /// let opt = AtomicOption::<u8>::new(None);
105    /// assert_eq!(opt.get().is_none(), true);
106    /// assert!(opt.is_none());
107    /// assert!(!opt.is_some());
108    ///
109    /// let b = opt.swap(Some(1));
110    /// assert_eq!(b, None);
111    /// assert_eq!(opt.get().is_none(), false);
112    /// assert!(!opt.is_none());
113    /// assert!(opt.is_some());
114    /// ```
115    pub fn get(&self) -> Option<&'static T> {
116        let value = self.0.load(Ordering::Relaxed);
117        if !value.is_null() {
118            Some(unsafe { &*value })
119        } else {
120            None
121        }
122    }
123
124    /// # Example
125    ///
126    /// ```no_run
127    /// use sync::atomic::AtomicOption;
128    ///
129    /// let opt = AtomicOption::<u8>::new(None);
130    /// assert_eq!(opt.get().is_none(), true);
131    /// assert!(opt.is_none());
132    /// assert!(!opt.is_some());
133    ///
134    /// let b = opt.swap(Some(1));
135    /// assert_eq!(b, None);
136    /// assert_eq!(opt.get().is_none(), false);
137    /// assert!(!opt.is_none());
138    /// assert!(opt.is_some());
139    /// ```
140    pub fn swap(&self, value: Option<T>) -> Option<T> {
141        let value = self.0.swap(
142            value
143                .map(|v| Box::into_raw(Box::new(v)))
144                .unwrap_or(null_mut()),
145            Ordering::Relaxed,
146        );
147
148        if !value.is_null() {
149            Some(unsafe { *Box::from_raw(value) })
150        } else {
151            None
152        }
153    }
154
155    /// # Example
156    ///
157    /// ```no_run
158    /// use sync::atomic::AtomicOption;
159    ///
160    /// let opt = AtomicOption::<u8>::new(None);
161    /// assert_eq!(opt.get().is_none(), true);
162    /// assert!(opt.is_none());
163    /// assert!(!opt.is_some());
164    ///
165    /// let b = opt.swap(Some(1));
166    /// assert_eq!(b, None);
167    /// assert_eq!(opt.get().is_none(), false);
168    /// assert!(!opt.is_none());
169    /// assert!(opt.is_some());
170    /// ```
171    pub fn is_none(&self) -> bool {
172        self.0.load(Ordering::Relaxed).is_null()
173    }
174
175    /// # Example
176    ///
177    /// ```no_run
178    /// use sync::atomic::AtomicOption;
179    ///
180    /// let opt = AtomicOption::<u8>::new(None);
181    /// assert_eq!(opt.get().is_none(), true);
182    /// assert!(opt.is_none());
183    /// assert!(!opt.is_some());
184    ///
185    /// let b = opt.swap(Some(1));
186    /// assert_eq!(b, None);
187    /// assert_eq!(opt.get().is_none(), false);
188    /// assert!(!opt.is_none());
189    /// assert!(opt.is_some());
190    /// ```
191    pub fn is_some(&self) -> bool {
192        !self.is_none()
193    }
194}
195
196impl<T> Drop for AtomicOption<T> {
197    fn drop(&mut self) {
198        drop(self.swap(None))
199    }
200}