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}