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}