atomic_traits/fetch.rs
1//! Fetch and apply operations to the current value, returning the previous value.
2use core::sync::atomic::Ordering;
3
4/// Bitwise "and" with the current value.
5pub trait And {
6 /// The underlying type
7 type Type;
8
9 /// Bitwise "and" with the current value.
10 ///
11 /// Performs a bitwise "and" operation on the current value and the argument `val`,
12 /// and sets the new value to the result.
13 ///
14 /// Returns the previous value.
15 ///
16 /// # Examples
17 ///
18 /// ```
19 /// use std::sync::atomic::{AtomicU8, Ordering};
20 /// use atomic_traits::{Atomic, fetch};
21 ///
22 /// let foo = AtomicU8::new(0b101101);
23 /// assert_eq!(fetch::And::fetch_and(&foo, 0b110011, Ordering::SeqCst), 0b101101);
24 /// assert_eq!(Atomic::load(&foo, Ordering::SeqCst), 0b100001);
25 /// ```
26 fn fetch_and(&self, val: Self::Type, order: Ordering) -> Self::Type;
27}
28
29/// Bitwise "nand" with the current value.
30#[cfg(any(feature = "atomic_nand", feature = "since_1_27_0"))]
31pub trait Nand {
32 /// The underlying type
33 type Type;
34
35 /// Bitwise "nand" with the current value.
36 ///
37 /// Performs a bitwise "nand" operation on the current value and the argument `val`,
38 /// and sets the new value to the result.
39 ///
40 /// Returns the previous value.
41 ///
42 /// # Examples
43 ///
44 /// ```
45 /// use std::sync::atomic::{AtomicU8, Ordering};
46 /// use atomic_traits::{Atomic, fetch};
47 ///
48 /// let foo = AtomicU8::new(0x13);
49 /// assert_eq!(fetch::Nand::fetch_nand(&foo, 0x31, Ordering::SeqCst), 0x13);
50 /// assert_eq!(Atomic::load(&foo, Ordering::SeqCst), !(0x13 & 0x31));
51 /// ```
52 fn fetch_nand(&self, val: Self::Type, order: Ordering) -> Self::Type;
53}
54
55/// Bitwise "or" with the current value.
56pub trait Or {
57 /// The underlying type
58 type Type;
59
60 /// Bitwise "or" with the current value.
61 ///
62 /// Performs a bitwise "or" operation on the current value and the argument `val`,
63 /// and sets the new value to the result.
64 ///
65 /// Returns the previous value.
66 ///
67 ///
68 /// # Examples
69 ///
70 /// ```
71 /// use std::sync::atomic::{AtomicU8, Ordering};
72 /// use atomic_traits::{Atomic, fetch};
73 ///
74 /// let foo = AtomicU8::new(0b101101);
75 /// assert_eq!(fetch::Or::fetch_or(&foo, 0b110011, Ordering::SeqCst), 0b101101);
76 /// assert_eq!(Atomic::load(&foo, Ordering::SeqCst), 0b111111);
77 /// ```
78 fn fetch_or(&self, val: Self::Type, order: Ordering) -> Self::Type;
79}
80
81/// Bitwise "xor" with the current value.
82pub trait Xor {
83 /// The underlying type
84 type Type;
85
86 /// Bitwise "xor" with the current value.
87 ///
88 /// Performs a bitwise "xor" operation on the current value and the argument `val`,
89 /// and sets the new value to the result.
90 ///
91 /// Returns the previous value.
92 ///
93 /// # Examples
94 ///
95 /// ```
96 /// use std::sync::atomic::{AtomicU8, Ordering};
97 /// use atomic_traits::{Atomic, fetch};
98 ///
99 /// let foo = AtomicU8::new(0b101101);
100 /// assert_eq!(fetch::Xor::fetch_xor(&foo, 0b110011, Ordering::SeqCst), 0b101101);
101 /// assert_eq!(Atomic::load(&foo, Ordering::SeqCst), 0b011110);
102 /// ```
103 fn fetch_xor(&self, val: Self::Type, order: Ordering) -> Self::Type;
104}
105
106/// Logical "not" with a boolean value.
107#[cfg(feature = "atomic_bool_fetch_not")]
108pub trait Not {
109 /// The underlying type
110 type Type;
111
112 /// Logical "not" with a boolean value.
113 ///
114 /// Performs a logical "not" operation on the current value, and sets
115 /// the new value to the result.
116 ///
117 /// Returns the previous value.
118 ///
119 /// # Examples
120 ///
121 /// ```
122 /// #![feature(atomic_bool_fetch_not)]
123 /// use std::sync::atomic::{AtomicBool, Ordering};
124 /// use atomic_traits::{Atomic, fetch};
125 ///
126 /// let foo = AtomicBool::new(true);
127 /// assert_eq!(fetch::Not::fetch_not(&foo, Ordering::SeqCst), true);
128 /// assert_eq!(Atomic::load(&foo, Ordering::SeqCst), false);
129 /// ```
130 fn fetch_not(&self, order: Ordering) -> Self::Type;
131}
132
133/// Adds to the current value, returning the previous value.
134pub trait Add {
135 /// The underlying type
136 type Type;
137
138 /// Adds to the current value, returning the previous value.
139 ///
140 /// This operation wraps around on overflow.
141 ///
142 /// # Examples
143 ///
144 /// ```
145 /// use std::sync::atomic::{AtomicU8, Ordering};
146 /// use atomic_traits::{Atomic, fetch};
147 ///
148 /// let foo = AtomicU8::new(0);
149 /// assert_eq!(fetch::Add::fetch_add(&foo, 10, Ordering::SeqCst), 0);
150 /// assert_eq!(Atomic::load(&foo, Ordering::SeqCst), 10);
151 /// ```
152 fn fetch_add(&self, val: Self::Type, order: Ordering) -> Self::Type;
153}
154
155/// Subtracts from the current value, returning the previous value.
156pub trait Sub {
157 /// The underlying type
158 type Type;
159
160 /// Subtracts from the current value, returning the previous value.
161 ///
162 /// This operation wraps around on overflow.
163 ///
164 /// # Examples
165 ///
166 /// ```
167 /// use std::sync::atomic::{AtomicU8, Ordering};
168 /// use atomic_traits::{Atomic, fetch};
169 ///
170 /// let foo = AtomicU8::new(20);
171 /// assert_eq!(fetch::Sub::fetch_sub(&foo, 10, Ordering::SeqCst), 20);
172 /// assert_eq!(Atomic::load(&foo, Ordering::SeqCst), 10);
173 /// ```
174 fn fetch_sub(&self, val: Self::Type, order: Ordering) -> Self::Type;
175}
176
177cfg_if! {
178 if #[cfg(any(feature = "since_1_45_0"))] {
179 /// Fetches the value, and applies a function to it that returns an optional new value.
180 pub trait Update {
181 /// The underlying type
182 type Type;
183
184 /// Fetches the value, and applies a function to it that returns an optional new value.
185 ///
186 /// Returns a `Result` of `Ok(previous_value)` if the function returned `Some(_)`, else `Err(previous_value)`.
187 ///
188 ///
189 /// # Examples
190 ///
191 /// ```rust
192 /// use std::sync::atomic::{AtomicU8, Ordering};
193 /// use atomic_traits::{Atomic, fetch};
194 ///
195 /// let x = AtomicU8::new(7);
196 /// assert_eq!(fetch::Update::fetch_update(&x, Ordering::SeqCst, Ordering::SeqCst, |_| None), Err(7));
197 /// assert_eq!(fetch::Update::fetch_update(&x, Ordering::SeqCst, Ordering::SeqCst, |x| Some(x + 1)), Ok(7));
198 /// assert_eq!(fetch::Update::fetch_update(&x, Ordering::SeqCst, Ordering::SeqCst, |x| Some(x + 1)), Ok(8));
199 /// assert_eq!(Atomic::load(&x, Ordering::SeqCst), 9);
200 /// ```
201 fn fetch_update<F>(
202 &self,
203 fetch_order: Ordering,
204 set_order: Ordering,
205 f: F,
206 ) -> Result<Self::Type, Self::Type>
207 where
208 F: FnMut(Self::Type) -> Option<Self::Type>;
209 }
210
211 /// Maximum with the current value.
212 pub trait Max {
213 /// The underlying type
214 type Type;
215
216 /// Maximum with the current value.
217 ///
218 /// Finds the maximum of the current value and the argument `val`, and sets the new value to the result.
219 ///
220 /// Returns the previous value.
221 ///
222 /// # Examples
223 ///
224 /// ```
225 /// use std::sync::atomic::{AtomicU8, Ordering};
226 /// use atomic_traits::{Atomic, fetch};
227 ///
228 /// let foo = AtomicU8::new(23);
229 /// assert_eq!(fetch::Max::fetch_max(&foo, 42, Ordering::SeqCst), 23);
230 /// assert_eq!(Atomic::load(&foo, Ordering::SeqCst), 42);
231 /// ```
232 fn fetch_max(&self, val: Self::Type, order: Ordering) -> Self::Type;
233 }
234
235 /// Minimum with the current value.
236 pub trait Min {
237 /// The underlying type
238 type Type;
239
240 /// Minimum with the current value.
241 ///
242 /// Finds the minimum of the current value and the argument `val`, and sets the new value to the result.
243 ///
244 /// Returns the previous value.
245 ///
246 /// # Examples
247 ///
248 /// ```
249 /// use std::sync::atomic::{AtomicU8, Ordering};
250 /// use atomic_traits::{Atomic, fetch};
251 ///
252 /// let foo = AtomicU8::new(23);
253 /// assert_eq!(fetch::Min::fetch_min(&foo, 42, Ordering::Relaxed), 23);
254 /// assert_eq!(Atomic::load(&foo, Ordering::Relaxed), 23);
255 /// assert_eq!(fetch::Min::fetch_min(&foo, 22, Ordering::Relaxed), 23);
256 /// assert_eq!(Atomic::load(&foo, Ordering::Relaxed), 22);
257 /// ```
258 fn fetch_min(&self, val: Self::Type, order: Ordering) -> Self::Type;
259 }
260 }
261}