keos/sync/
atomic.rs

1//! A wrapper around the core::sync::atomic.
2//!
3//! # Atomic types
4//!
5//! Atomic types provide primitive shared-memory communication between
6//! threads, and are the building blocks of other concurrent
7//! types.
8//!
9//! This module defines a wrapper to the atomic types defined in
10//! [`core::sync::atomic`], including [`AtomicBool`], [`AtomicIsize`],
11//! [`AtomicUsize`], [`AtomicI8`], [`AtomicU16`], etc.
12//! Atomic types present operations that, when used correctly, synchronize
13//! updates between threads.
14//!
15//! Atomic variables are safe to share between threads (they implement [`Sync`])
16//! but they do not themselves provide the mechanism for sharing and follow the
17//! [threading model](https://doc.rust-lang.org/std/thread/#the-threading-model) of
18//! Rust. The most common way to share an atomic variable is to put it into an
19//! [`Arc`][arc] (an atomically-reference-counted shared pointer).
20//!
21//! [arc]: https://doc.rust-lang.org/beta/std/sync/struct.Arc.html
22//! [`core::sync::atomic`]: https://doc.rust-lang.org/core/sync/atomic/
23//! [`Sync`]: https://doc.rust-lang.org/beta/core/marker/trait.Sync.html
24
25use core::sync::atomic::Ordering;
26
27/// A boolean type which can be safely shared between threads.
28///
29/// This type has the same size, alignment, and bit validity as a [`bool`].
30#[derive(Default)]
31pub struct AtomicBool(core::sync::atomic::AtomicBool);
32
33/// A raw pointer type which can be safely shared between threads.
34///
35/// This type has the same size and bit validity as a `*mut T`.
36///
37/// **Note**: This type is only available on platforms that support atomic
38/// loads and stores of pointers. Its size depends on the target pointer's size.
39#[derive(Default)]
40pub struct AtomicPtr<T>(core::sync::atomic::AtomicPtr<T>);
41
42impl AtomicBool {
43    /// Creates a new `AtomicBool`.
44    ///
45    /// # Examples
46    ///
47    /// ```
48    /// use KeOS::sync::atomic::AtomicBool;
49    ///
50    /// let atomic_true = AtomicBool::new(true);
51    /// let atomic_false = AtomicBool::new(false);
52    /// ```
53    #[inline]
54    #[must_use]
55    pub const fn new(v: bool) -> AtomicBool {
56        Self(core::sync::atomic::AtomicBool::new(v))
57    }
58
59    /// Returns a mutable reference to the underlying [`bool`].
60    ///
61    /// This is safe because the mutable reference guarantees that no other
62    /// threads are concurrently accessing the atomic data.
63    ///
64    /// # Examples
65    ///
66    /// ```
67    /// use keos::atomic::AtomicBool;
68    ///
69    /// let mut some_bool = AtomicBool::new(true);
70    /// assert_eq!(*some_bool.get_mut(), true);
71    /// *some_bool.get_mut() = false;
72    /// assert_eq!(some_bool.load(), false);
73    /// ```
74    #[inline]
75    pub fn get_mut(&mut self) -> &mut bool {
76        self.0.get_mut()
77    }
78
79    /// Consumes the atomic and returns the contained value.
80    ///
81    /// This is safe because passing `self` by value guarantees that no other
82    /// threads are concurrently accessing the atomic data.
83    ///
84    /// # Examples
85    ///
86    /// ```
87    /// use keos::atomic::AtomicBool;
88    ///
89    /// let some_bool = AtomicBool::new(true);
90    /// assert_eq!(some_bool.into_inner(), true);
91    /// ```
92    #[inline]
93    pub const fn into_inner(self) -> bool {
94        self.0.into_inner()
95    }
96
97    /// Loads a value from the bool.
98    ///
99    /// # Examples
100    ///
101    /// ```
102    /// use keos::atomic::AtomicBool;
103    ///
104    /// let some_bool = AtomicBool::new(true);
105    ///
106    /// assert_eq!(some_bool.load(), true);
107    /// ```
108    #[inline]
109    pub fn load(&self) -> bool {
110        self.0.load(Ordering::SeqCst)
111    }
112
113    /// Stores a value into the bool.
114    ///
115    ///
116    /// # Examples
117    ///
118    /// ```
119    /// use keos::atomic::AtomicBool;
120    ///
121    /// let some_bool = AtomicBool::new(true);
122    ///
123    /// some_bool.store(false);
124    /// assert_eq!(some_bool.load(), false);
125    /// ```
126    #[inline]
127    pub fn store(&self, val: bool) {
128        self.0.store(val, Ordering::SeqCst)
129    }
130
131    /// Stores a value into the bool, returning the previous value.
132    ///
133    /// # Examples
134    ///
135    /// ```
136    /// use keos::atomic::AtomicBool;
137    ///
138    /// let some_bool = AtomicBool::new(true);
139    ///
140    /// assert_eq!(some_bool.swap(false), true);
141    /// assert_eq!(some_bool.load(), false);
142    /// ```
143    #[inline]
144    pub fn swap(&self, val: bool) -> bool {
145        self.0.swap(val, Ordering::SeqCst)
146    }
147
148    /// Stores a value into the [`bool`] if the current value is the same as the
149    /// `current` value.
150    ///
151    /// The return value is a result indicating whether the new value was
152    /// written and containing the previous value. On success this value is
153    /// guaranteed to be equal to `current`.
154    ///
155    /// # Examples
156    ///
157    /// ```
158    /// use std::sync::atomic::AtomicBool;
159    ///
160    /// let some_bool = AtomicBool::new(true);
161    ///
162    /// assert_eq!(some_bool.compare_exchange(true, false), Ok(true));
163    /// assert_eq!(some_bool.load(), false);
164    ///
165    /// assert_eq!(some_bool.compare_exchange(true, true), Err(false));
166    /// assert_eq!(some_bool.load(), false);
167    /// ```
168    #[inline]
169    pub fn compare_exchange(&self, current: bool, new: bool) -> Result<bool, bool> {
170        self.0
171            .compare_exchange(current, new, Ordering::SeqCst, Ordering::SeqCst)
172    }
173
174    /// Logical "and" with a boolean value.
175    ///
176    /// Performs a logical "and" operation on the current value and the argument
177    /// `val`, and sets the new value to the result.
178    ///
179    /// Returns the previous value.
180    ///
181    /// # Examples
182    ///
183    /// ```
184    /// use keos::atomic::AtomicBool;
185    ///
186    /// let foo = AtomicBool::new(true);
187    /// assert_eq!(foo.fetch_and(false), true);
188    /// assert_eq!(foo.load(), false);
189    ///
190    /// let foo = AtomicBool::new(true);
191    /// assert_eq!(foo.fetch_and(true), true);
192    /// assert_eq!(foo.load(), true);
193    ///
194    /// let foo = AtomicBool::new(false);
195    /// assert_eq!(foo.fetch_and(false), false);
196    /// assert_eq!(foo.load(), false);
197    /// ```
198    #[inline]
199    pub fn fetch_and(&self, val: bool) -> bool {
200        self.0.fetch_and(val, Ordering::SeqCst)
201    }
202
203    /// Logical "nand" with a boolean value.
204    ///
205    /// Performs a logical "nand" operation on the current value and the
206    /// argument `val`, and sets the new value to the result.
207    ///
208    /// Returns the previous value.
209    ///
210    /// **Note:** This method is only available on platforms that support atomic
211    /// operations on `u8`.
212    ///
213    /// # Examples
214    ///
215    /// ```
216    /// use keos::atomic::{AtomicBool, Ordering};
217    ///
218    /// let foo = AtomicBool::new(true);
219    /// assert_eq!(foo.fetch_nand(false), true);
220    /// assert_eq!(foo.load(), true);
221    ///
222    /// let foo = AtomicBool::new(true);
223    /// assert_eq!(foo.fetch_nand(true), true);
224    /// assert_eq!(foo.load() as usize, 0);
225    /// assert_eq!(foo.load(), false);
226    ///
227    /// let foo = AtomicBool::new(false);
228    /// assert_eq!(foo.fetch_nand(false), false);
229    /// assert_eq!(foo.load(), true);
230    /// ```
231    #[inline]
232    pub fn fetch_nand(&self, val: bool) -> bool {
233        self.0.fetch_nand(val, Ordering::SeqCst)
234    }
235
236    /// Logical "or" with a boolean value.
237    ///
238    /// Performs a logical "or" operation on the current value and the argument
239    /// `val`, and sets the new value to the result.
240    ///
241    /// Returns the previous value.
242    ///
243    /// **Note:** This method is only available on platforms that support atomic
244    /// operations on `u8`.
245    ///
246    /// # Examples
247    ///
248    /// ```
249    /// use keos::atomic::{AtomicBool, Ordering};
250    ///
251    /// let foo = AtomicBool::new(true);
252    /// assert_eq!(foo.fetch_or(false), true);
253    /// assert_eq!(foo.load(), true);
254    ///
255    /// let foo = AtomicBool::new(true);
256    /// assert_eq!(foo.fetch_or(true), true);
257    /// assert_eq!(foo.load(), true);
258    ///
259    /// let foo = AtomicBool::new(false);
260    /// assert_eq!(foo.fetch_or(false), false);
261    /// assert_eq!(foo.load(), false);
262    /// ```
263    #[inline]
264    pub fn fetch_or(&self, val: bool) -> bool {
265        self.0.fetch_or(val, Ordering::SeqCst)
266    }
267
268    /// Logical "xor" with a boolean value.
269    ///
270    /// Performs a logical "xor" operation on the current value and the argument
271    /// `val`, and sets the new value to the result.
272    ///
273    /// Returns the previous value.
274    ///
275    /// **Note:** This method is only available on platforms that support atomic
276    /// operations on `u8`.
277    ///
278    /// # Examples
279    ///
280    /// ```
281    /// use keos::atomic::{AtomicBool, Ordering};
282    ///
283    /// let foo = AtomicBool::new(true);
284    /// assert_eq!(foo.fetch_xor(false), true);
285    /// assert_eq!(foo.load(), true);
286    ///
287    /// let foo = AtomicBool::new(true);
288    /// assert_eq!(foo.fetch_xor(true), true);
289    /// assert_eq!(foo.load(), false);
290    ///
291    /// let foo = AtomicBool::new(false);
292    /// assert_eq!(foo.fetch_xor(false), false);
293    /// assert_eq!(foo.load(), false);
294    /// ```
295    #[inline]
296    pub fn fetch_xor(&self, val: bool) -> bool {
297        self.0.fetch_xor(val, Ordering::SeqCst)
298    }
299
300    /// Logical "not" with a boolean value.
301    ///
302    /// Performs a logical "not" operation on the current value, and sets
303    /// the new value to the result.
304    ///
305    /// Returns the previous value.
306    ///
307    /// **Note:** This method is only available on platforms that support atomic
308    /// operations on `u8`.
309    ///
310    /// # Examples
311    ///
312    /// ```
313    /// use keos::atomic::AtomicBool;
314    ///
315    /// let foo = AtomicBool::new(true);
316    /// assert_eq!(foo.fetch_not(), true);
317    /// assert_eq!(foo.load(), false);
318    ///
319    /// let foo = AtomicBool::new(false);
320    /// assert_eq!(foo.fetch_not(), false);
321    /// assert_eq!(foo.load(), true);
322    /// ```
323    #[inline]
324    pub fn fetch_not(&self) -> bool {
325        self.0.fetch_not(Ordering::SeqCst)
326    }
327
328    /// Fetches the value, and applies a function to it that returns an optional
329    /// new value. Returns a `Result` of `Ok(previous_value)` if the function
330    /// returned `Some(_)`, else `Err(previous_value)`.
331    ///
332    /// Note: This may call the function multiple times if the value has been
333    /// changed from other threads in the meantime, as long as the function
334    /// returns `Some(_)`, but the function will have been applied only once to
335    /// the stored value.
336    ///
337    /// # Examples
338    ///
339    /// ```rust
340    /// use keos::atomic::AtomicBool;
341    ///
342    /// let x = AtomicBool::new(false);
343    /// assert_eq!(x.fetch_update(|_| None), Err(false));
344    /// assert_eq!(x.fetch_update(|x| Some(!x)), Ok(false));
345    /// assert_eq!(x.fetch_update(|x| Some(!x)), Ok(true));
346    /// assert_eq!(x.load(), false);
347    /// ```
348    #[inline]
349    pub fn fetch_update<F>(&self, f: F) -> Result<bool, bool>
350    where
351        F: FnMut(bool) -> Option<bool>,
352    {
353        self.0.fetch_update(Ordering::SeqCst, Ordering::SeqCst, f)
354    }
355}
356
357impl<T> AtomicPtr<T> {
358    /// Creates a new `AtomicPtr`.
359    ///
360    /// # Examples
361    ///
362    /// ```
363    /// use keos::atomic::AtomicPtr;
364    ///
365    /// let ptr = &mut 5;
366    /// let atomic_ptr = AtomicPtr::new(ptr);
367    /// ```
368    #[inline]
369    pub const fn new(p: *mut T) -> AtomicPtr<T> {
370        Self(core::sync::atomic::AtomicPtr::new(p))
371    }
372
373    /// Returns a mutable reference to the underlying pointer.
374    ///
375    /// This is safe because the mutable reference guarantees that no other
376    /// threads are concurrently accessing the atomic data.
377    ///
378    /// # Examples
379    ///
380    /// ```
381    /// use keos::atomic::AtomicPtr;
382    ///
383    /// let mut data = 10;
384    /// let mut atomic_ptr = AtomicPtr::new(&mut data);
385    /// let mut other_data = 5;
386    /// *atomic_ptr.get_mut() = &mut other_data;
387    /// assert_eq!(unsafe { *atomic_ptr.load() }, 5);
388    /// ```
389    #[inline]
390    pub fn get_mut(&mut self) -> &mut *mut T {
391        self.0.get_mut()
392    }
393
394    /// Consumes the atomic and returns the contained value.
395    ///
396    /// This is safe because passing `self` by value guarantees that no other
397    /// threads are concurrently accessing the atomic data.
398    ///
399    /// # Examples
400    ///
401    /// ```
402    /// use keos::atomic::AtomicPtr;
403    ///
404    /// let mut data = 5;
405    /// let atomic_ptr = AtomicPtr::new(&mut data);
406    /// assert_eq!(unsafe { *atomic_ptr.into_inner() }, 5);
407    /// ```
408    #[inline]
409    pub const fn into_inner(self) -> *mut T {
410        self.0.into_inner()
411    }
412
413    /// Loads a value from the pointer.
414    ///
415    ///
416    /// # Examples
417    ///
418    /// ```
419    /// use keos::atomic::AtomicPtr;
420    ///
421    /// let ptr = &mut 5;
422    /// let some_ptr = AtomicPtr::new(ptr);
423    ///
424    /// let value = some_ptr.load();
425    /// ```
426    #[inline]
427    pub fn load(&self) -> *mut T {
428        self.0.load(Ordering::SeqCst)
429    }
430
431    /// Stores a value into the pointer.
432    ///
433    /// # Examples
434    ///
435    /// ```
436    /// use keos::atomic::AtomicPtr;
437    ///
438    /// let ptr = &mut 5;
439    /// let some_ptr = AtomicPtr::new(ptr);
440    ///
441    /// let other_ptr = &mut 10;
442    ///
443    /// some_ptr.store(other_ptr);
444    /// ```
445    #[inline]
446    pub fn store(&self, ptr: *mut T) {
447        self.0.store(ptr, Ordering::SeqCst);
448    }
449
450    /// Stores a value into the pointer, returning the previous value.
451    ///
452    /// # Examples
453    ///
454    /// ```
455    /// use keos::atomic::AtomicPtr;
456    ///
457    /// let ptr = &mut 5;
458    /// let some_ptr = AtomicPtr::new(ptr);
459    ///
460    /// let other_ptr = &mut 10;
461    ///
462    /// let value = some_ptr.swap(other_ptr);
463    /// ```
464    #[inline]
465    pub fn swap(&self, ptr: *mut T) -> *mut T {
466        self.0.swap(ptr, Ordering::SeqCst)
467    }
468
469    /// Stores a value into the pointer if the current value is the same as the
470    /// `current` value.
471    ///
472    /// The return value is a result indicating whether the new value was
473    /// written and containing the previous value. On success this value is
474    /// guaranteed to be equal to `current`.
475    ///
476    ///
477    /// # Examples
478    ///
479    /// ```
480    /// use keos::atomic::AtomicPtr;
481    ///
482    /// let ptr = &mut 5;
483    /// let some_ptr = AtomicPtr::new(ptr);
484    ///
485    /// let other_ptr = &mut 10;
486    ///
487    /// let value = some_ptr.compare_exchange(ptr, other_ptr);
488    /// ```
489    #[inline]
490    pub fn compare_exchange(&self, current: *mut T, new: *mut T) -> Result<*mut T, *mut T> {
491        self.0
492            .compare_exchange(current, new, Ordering::SeqCst, Ordering::SeqCst)
493    }
494
495    /// Fetches the value, and applies a function to it that returns an optional
496    /// new value. Returns a `Result` of `Ok(previous_value)` if the function
497    /// returned `Some(_)`, else `Err(previous_value)`.
498    ///
499    /// Note: This may call the function multiple times if the value has been
500    /// changed from other threads in the meantime, as long as the function
501    /// returns `Some(_)`, but the function will have been applied only once to
502    /// the stored value.
503    ///
504    /// # Examples
505    ///
506    /// ```rust
507    /// use keos::atomic::AtomicPtr;
508    ///
509    /// let ptr: *mut _ = &mut 5;
510    /// let some_ptr = AtomicPtr::new(ptr);
511    ///
512    /// let new: *mut _ = &mut 10;
513    /// assert_eq!(some_ptr.fetch_update(, |_| None), Err(ptr));
514    /// let result = some_ptr.fetch_update(, |x| {
515    ///     if x == ptr {
516    ///         Some(new)
517    ///     } else {
518    ///         None
519    ///     }
520    /// });
521    /// assert_eq!(result, Ok(ptr));
522    /// assert_eq!(some_ptr.load(), new);
523    /// ```
524    #[inline]
525    pub fn fetch_update<F>(&self, f: F) -> Result<*mut T, *mut T>
526    where
527        F: FnMut(*mut T) -> Option<*mut T>,
528    {
529        self.0.fetch_update(Ordering::SeqCst, Ordering::SeqCst, f)
530    }
531
532    /// Returns a mutable pointer to the underlying pointer.
533    ///
534    /// Doing non-atomic reads and writes on the resulting pointer can be a data
535    /// race. This method is mostly useful for FFI, where the function
536    /// signature may use `*mut *mut T` instead of `&AtomicPtr<T>`.
537    ///
538    /// Returning an `*mut` pointer from a shared reference to this atomic is
539    /// safe because the atomic types work with interior mutability. All
540    /// modifications of an atomic change the value through a shared
541    /// reference, and can do so safely as long as they use atomic operations.
542    /// Any use of the returned raw pointer requires an `unsafe` block and
543    /// still has to uphold the same restriction: operations on it must be
544    /// atomic.
545    ///
546    /// # Examples
547    ///
548    /// ```ignore (extern-declaration)
549    /// use keos::atomic::AtomicPtr;
550    ///
551    /// extern "C" {
552    ///     fn my_atomic_op(arg: *mut *mut u32);
553    /// }
554    ///
555    /// let mut value = 17;
556    /// let atomic = AtomicPtr::new(&mut value);
557    ///
558    /// // SAFETY: Safe as long as `my_atomic_op` is atomic.
559    /// unsafe {
560    ///     my_atomic_op(atomic.as_ptr());
561    /// }
562    /// ```
563    #[inline]
564    pub const fn as_ptr(&self) -> *mut *mut T {
565        self.0.as_ptr()
566    }
567}
568
569impl From<bool> for AtomicBool {
570    /// Converts a `bool` into an `AtomicBool`.
571    ///
572    /// # Examples
573    ///
574    /// ```
575    /// use keos::atomic::AtomicBool;
576    /// let atomic_bool = AtomicBool::from(true);
577    /// assert_eq!(format!("{atomic_bool:?}"), "true")
578    /// ```
579    #[inline]
580    fn from(b: bool) -> Self {
581        Self::new(b)
582    }
583}
584
585impl<T> From<*mut T> for AtomicPtr<T> {
586    /// Converts a `*mut T` into an `AtomicPtr<T>`.
587    #[inline]
588    fn from(p: *mut T) -> Self {
589        Self::new(p)
590    }
591}
592
593#[allow(unused_macros)] // This macro ends up being unused on some architectures.
594macro_rules! if_8_bit {
595    (u8, $( yes = [$($yes:tt)*], )? $( no = [$($no:tt)*], )? ) => { concat!("", $($($yes)*)?) };
596    (i8, $( yes = [$($yes:tt)*], )? $( no = [$($no:tt)*], )? ) => { concat!("", $($($yes)*)?) };
597    ($_:ident, $( yes = [$($yes:tt)*], )? $( no = [$($no:tt)*], )? ) => { concat!("", $($($no)*)?) };
598}
599
600macro_rules! atomic_int {
601    ($s_int_type:literal,
602     $extra_feature:expr,
603     $int_type:ident $atomic_type:ident) => {
604        /// An integer type which can be safely shared between threads.
605        ///
606        /// This type has the same
607        #[doc = if_8_bit!(
608            $int_type,
609            yes = ["size, alignment, and bit validity"],
610            no = ["size and bit validity"],
611        )]
612        /// as the underlying integer type, [`
613        #[doc = $s_int_type]
614        /// `].
615        #[doc = if_8_bit! {
616            $int_type,
617            no = [
618                "However, the alignment of this type is always equal to its ",
619                "size, even on targets where [`", $s_int_type, "`] has a ",
620                "lesser alignment."
621            ],
622        }]
623        ///
624        /// For more about the differences between atomic types and
625        /// non-atomic types as well as information about the portability of
626        /// this type, please see the [module-level documentation].
627        ///
628        /// **Note:** This type is only available on platforms that support
629        /// atomic loads and stores of [`
630        #[doc = $s_int_type]
631        /// `].
632        ///
633        #[repr(transparent)]
634        #[derive(Default)]
635        pub struct $atomic_type(core::sync::atomic::$atomic_type);
636
637        impl From<$int_type> for $atomic_type {
638            #[doc = concat!("Converts an `", stringify!($int_type), "` into an `", stringify!($atomic_type), "`.")]
639            #[inline]
640            fn from(v: $int_type) -> Self { Self::new(v) }
641        }
642
643        impl core::fmt::Debug for $atomic_type {
644            fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
645                core::fmt::Debug::fmt(&self.load(), f)
646            }
647        }
648
649        impl $atomic_type {
650            /// Creates a new atomic integer.
651            ///
652            /// # Examples
653            ///
654            /// ```
655            #[doc = concat!($extra_feature, "use keos::atomic::", stringify!($atomic_type), ";")]
656            ///
657            #[doc = concat!("let atomic_forty_two = ", stringify!($atomic_type), "::new(42);")]
658            /// ```
659            #[inline]
660            #[must_use]
661            pub const fn new(v: $int_type) -> Self {
662                Self(core::sync::atomic::$atomic_type::new(v))
663            }
664
665            /// Returns a mutable reference to the underlying integer.
666            ///
667            /// This is safe because the mutable reference guarantees that no other threads are
668            /// concurrently accessing the atomic data.
669            ///
670            /// # Examples
671            ///
672            /// ```
673            #[doc = concat!($extra_feature, "use keos::atomic::", stringify!($atomic_type), ";")]
674            ///
675            #[doc = concat!("let mut some_var = ", stringify!($atomic_type), "::new(10);")]
676            /// assert_eq!(*some_var.get_mut(), 10);
677            /// *some_var.get_mut() = 5;
678            /// assert_eq!(some_var.load(), 5);
679            /// ```
680            #[inline]
681            pub fn get_mut(&mut self) -> &mut $int_type {
682                self.0.get_mut()
683            }
684
685            /// Consumes the atomic and returns the contained value.
686            ///
687            /// This is safe because passing `self` by value guarantees that no other threads are
688            /// concurrently accessing the atomic data.
689            ///
690            /// # Examples
691            ///
692            /// ```
693            #[doc = concat!($extra_feature, "use keos::atomic::", stringify!($atomic_type), ";")]
694            ///
695            #[doc = concat!("let some_var = ", stringify!($atomic_type), "::new(5);")]
696            /// assert_eq!(some_var.into_inner(), 5);
697            /// ```
698            #[inline]
699            pub const fn into_inner(self) -> $int_type {
700                self.0.into_inner()
701            }
702
703            /// Loads a value from the atomic integer.
704            ///
705            /// # Examples
706            ///
707            /// ```
708            #[doc = concat!($extra_feature, "use keos::atomic::", stringify!($atomic_type), ";")]
709            ///
710            #[doc = concat!("let some_var = ", stringify!($atomic_type), "::new(5);")]
711            ///
712            /// assert_eq!(some_var.load(d), 5);
713            /// ```
714            #[inline]
715            pub fn load(&self) -> $int_type {
716                self.0.load(Ordering::SeqCst)
717            }
718
719            /// Stores a value into the atomic integer.
720            ///
721            /// # Examples
722            ///
723            /// ```
724            #[doc = concat!($extra_feature, "use keos::atomic::", stringify!($atomic_type), ";")]
725            ///
726            #[doc = concat!("let some_var = ", stringify!($atomic_type), "::new(5);")]
727            ///
728            /// some_var.store(10d);
729            /// assert_eq!(some_var.load(d), 10);
730            /// ```
731            #[inline]
732            pub fn store(&self, val: $int_type) {
733                self.0.store(val, Ordering::SeqCst)
734            }
735
736            /// Stores a value into the atomic integer, returning the previous value.
737            ///
738            /// # Examples
739            ///
740            /// ```
741            #[doc = concat!($extra_feature, "use keos::atomic::", stringify!($atomic_type), ";")]
742            ///
743            #[doc = concat!("let some_var = ", stringify!($atomic_type), "::new(5);")]
744            ///
745            /// assert_eq!(some_var.swap(10d), 5);
746            /// ```
747            #[inline]
748            pub fn swap(&self, val: $int_type) -> $int_type {
749                self.0.swap(val, Ordering::SeqCst)
750            }
751
752            /// Stores a value into the atomic integer if the current value is the same as
753            /// the `current` value.
754            ///
755            /// The return value is a result indicating whether the new value was written and
756            /// containing the previous value. On success this value is guaranteed to be equal to
757            /// `current`.
758            ///
759            /// # Examples
760            ///
761            /// ```
762            #[doc = concat!($extra_feature, "use keos::atomic::", stringify!($atomic_type), ";")]
763            ///
764            #[doc = concat!("let some_var = ", stringify!($atomic_type), "::new(5);")]
765            ///
766            /// assert_eq!(some_var.compare_exchange(5, 10, e), Ok(5));
767            /// assert_eq!(some_var.load(d), 10);
768            ///
769            /// assert_eq!(some_var.compare_exchange(6, 12, e), Err(10));
770            /// assert_eq!(some_var.load(d), 10);
771            /// ```
772            #[inline]
773            pub fn compare_exchange(&self,
774                                    current: $int_type,
775                                    new: $int_type) -> Result<$int_type, $int_type> {
776                self.0.compare_exchange(current, new, Ordering::SeqCst, Ordering::SeqCst)
777            }
778
779
780            /// Adds to the current value, returning the previous value.
781            ///
782            /// This operation wraps around on overflow.
783            ///
784            /// # Examples
785            ///
786            /// ```
787            #[doc = concat!($extra_feature, "use keos::atomic::", stringify!($atomic_type), ";")]
788            ///
789            #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(0);")]
790            /// assert_eq!(foo.fetch_add(10), 0);
791            /// assert_eq!(foo.load(), 10);
792            /// ```
793            #[inline]
794            pub fn fetch_add(&self, val: $int_type) -> $int_type {
795                self.0.fetch_add(val, Ordering::SeqCst)
796            }
797
798            /// Subtracts from the current value, returning the previous value.
799            ///
800            /// This operation wraps around on overflow.
801            ///
802            /// # Examples
803            ///
804            /// ```
805            #[doc = concat!($extra_feature, "use keos::atomic::", stringify!($atomic_type), ";")]
806            ///
807            #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(20);")]
808            /// assert_eq!(foo.fetch_sub(10), 20);
809            /// assert_eq!(foo.load(), 10);
810            /// ```
811            #[inline]
812            pub fn fetch_sub(&self, val: $int_type) -> $int_type {
813                self.0.fetch_sub(val, Ordering::SeqCst)
814            }
815
816            /// Bitwise "and" with the current value.
817            ///
818            /// Performs a bitwise "and" operation on the current value and the argument `val`, and
819            /// sets the new value to the result.
820            ///
821            /// Returns the previous value.
822            ///
823            /// # Examples
824            ///
825            /// ```
826            #[doc = concat!($extra_feature, "use keos::atomic::", stringify!($atomic_type), ";")]
827            ///
828            #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(0b101101);")]
829            /// assert_eq!(foo.fetch_and(0b110011), 0b101101);
830            /// assert_eq!(foo.load(), 0b100001);
831            /// ```
832            #[inline]
833            pub fn fetch_and(&self, val: $int_type) -> $int_type {
834                self.0.fetch_and(val, Ordering::SeqCst)
835            }
836
837            /// Bitwise "nand" with the current value.
838            ///
839            /// Performs a bitwise "nand" operation on the current value and the argument `val`, and
840            /// sets the new value to the result.
841            ///
842            /// Returns the previous value.
843            ///
844            /// # Examples
845            ///
846            /// ```
847            #[doc = concat!($extra_feature, "use keos::atomic::", stringify!($atomic_type), ";")]
848            ///
849            #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(0x13);")]
850            /// assert_eq!(foo.fetch_nand(0x31), 0x13);
851            /// assert_eq!(foo.load(), !(0x13 & 0x31));
852            /// ```
853            #[inline]
854            pub fn fetch_nand(&self, val: $int_type) -> $int_type {
855                self.0.fetch_nand(val, Ordering::SeqCst)
856            }
857
858            /// Bitwise "or" with the current value.
859            ///
860            /// Performs a bitwise "or" operation on the current value and the argument `val`, and
861            /// sets the new value to the result.
862            ///
863            /// Returns the previous value.
864            ///
865            /// # Examples
866            ///
867            /// ```
868            #[doc = concat!($extra_feature, "use keos::atomic::", stringify!($atomic_type), ";")]
869            ///
870            #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(0b101101);")]
871            /// assert_eq!(foo.fetch_or(0b110011), 0b101101);
872            /// assert_eq!(foo.load(), 0b111111);
873            /// ```
874            #[inline]
875            pub fn fetch_or(&self, val: $int_type) -> $int_type {
876                self.0.fetch_or(val, Ordering::SeqCst)
877            }
878
879            /// Bitwise "xor" with the current value.
880            ///
881            /// Performs a bitwise "xor" operation on the current value and the argument `val`, and
882            /// sets the new value to the result.
883            ///
884            /// Returns the previous value.
885            ///
886            /// # Examples
887            ///
888            /// ```
889            #[doc = concat!($extra_feature, "use keos::atomic::", stringify!($atomic_type), ";")]
890            ///
891            #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(0b101101);")]
892            /// assert_eq!(foo.fetch_xor(0b110011), 0b101101);
893            /// assert_eq!(foo.load(), 0b011110);
894            /// ```
895            #[inline]
896            pub fn fetch_xor(&self, val: $int_type) -> $int_type {
897                self.0.fetch_xor(val, Ordering::SeqCst)
898            }
899
900            /// Fetches the value, and applies a function to it that returns an optional
901            /// new value. Returns a `Result` of `Ok(previous_value)` if the function returned `Some(_)`, else
902            /// `Err(previous_value)`.
903            ///
904            /// Note: This may call the function multiple times if the value has been changed from other threads in
905            /// the meantime, as long as the function returns `Some(_)`, but the function will have been applied
906            /// only once to the stored value.
907            ///
908            /// # Examples
909            ///
910            /// ```rust
911            #[doc = concat!($extra_feature, "use keos::atomic::", stringify!($atomic_type), ";")]
912            ///
913            #[doc = concat!("let x = ", stringify!($atomic_type), "::new(7);")]
914            /// assert_eq!(x.fetch_update(|_| None), Err(7));
915            /// assert_eq!(x.fetch_update(|x| Some(x + 1)), Ok(7));
916            /// assert_eq!(x.fetch_update(|x| Some(x + 1)), Ok(8));
917            /// assert_eq!(x.load(), 9);
918            /// ```
919            #[inline]
920            pub fn fetch_update<F>(&self, f: F) -> Result<$int_type, $int_type>
921            where F: FnMut($int_type) -> Option<$int_type> {
922                self.0.fetch_update(Ordering::SeqCst, Ordering::SeqCst, f)
923            }
924
925            /// Maximum with the current value.
926            ///
927            /// Finds the maximum of the current value and the argument `val`, and
928            /// sets the new value to the result.
929            ///
930            /// Returns the previous value.
931            ///
932            /// # Examples
933            ///
934            /// ```
935            #[doc = concat!($extra_feature, "use keos::atomic::", stringify!($atomic_type), ";")]
936            ///
937            #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(23);")]
938            /// assert_eq!(foo.fetch_max(42), 23);
939            /// assert_eq!(foo.load(), 42);
940            /// ```
941            ///
942            /// If you want to obtain the maximum value in one step, you can use the following:
943            ///
944            /// ```
945            #[doc = concat!($extra_feature, "use keos::atomic::", stringify!($atomic_type), ";")]
946            ///
947            #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(23);")]
948            /// let bar = 42;
949            /// let max_foo = foo.fetch_max(bar).max(bar);
950            /// assert!(max_foo == 42);
951            /// ```
952            #[inline]
953            pub fn fetch_max(&self, val: $int_type) -> $int_type {
954                self.0.fetch_max(val, Ordering::SeqCst)
955            }
956
957            /// Minimum with the current value.
958            ///
959            /// Finds the minimum of the current value and the argument `val`, and
960            /// sets the new value to the result.
961            ///
962            /// Returns the previous value.
963            ///
964            /// # Examples
965            ///
966            /// ```
967            #[doc = concat!($extra_feature, "use keos::atomic::", stringify!($atomic_type), ";")]
968            ///
969            #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(23);")]
970            /// assert_eq!(foo.fetch_min(42d), 23);
971            /// assert_eq!(foo.load(d), 23);
972            /// assert_eq!(foo.fetch_min(22d), 23);
973            /// assert_eq!(foo.load(d), 22);
974            /// ```
975            ///
976            /// If you want to obtain the minimum value in one step, you can use the following:
977            ///
978            /// ```
979            #[doc = concat!($extra_feature, "use keos::atomic::", stringify!($atomic_type), ";")]
980            ///
981            #[doc = concat!("let foo = ", stringify!($atomic_type), "::new(23);")]
982            /// let bar = 12;
983            /// let min_foo = foo.fetch_min(bar).min(bar);
984            /// assert_eq!(min_foo, 12);
985            /// ```
986            #[inline]
987            pub fn fetch_min(&self, val: $int_type) -> $int_type {
988                self.0.fetch_min(val, Ordering::SeqCst)
989            }
990
991            /// Returns a mutable pointer to the underlying integer.
992            ///
993            /// Doing non-atomic reads and writes on the resulting integer can be a data race.
994            /// This method is mostly useful for FFI, where the function signature may use
995            #[doc = concat!("`*mut ", stringify!($int_type), "` instead of `&", stringify!($atomic_type), "`.")]
996            ///
997            /// Returning an `*mut` pointer from a shared reference to this atomic is safe because the
998            /// atomic types work with interior mutability. All modifications of an atomic change the value
999            /// through a shared reference, and can do so safely as long as they use atomic operations. Any
1000            /// use of the returned raw pointer requires an `unsafe` block and still has to uphold the same
1001            /// restriction: operations on it must be atomic.
1002            ///
1003            /// # Examples
1004            ///
1005            /// ```ignore (extern-declaration)
1006            /// # fn main() {
1007            #[doc = concat!($extra_feature, "use keos::atomic::", stringify!($atomic_type), ";")]
1008            ///
1009            /// extern "C" {
1010            #[doc = concat!("    fn my_atomic_op(arg: *mut ", stringify!($int_type), ");")]
1011            /// }
1012            ///
1013            #[doc = concat!("let atomic = ", stringify!($atomic_type), "::new(1);")]
1014            ///
1015            /// // SAFETY: Safe as long as `my_atomic_op` is atomic.
1016            /// unsafe {
1017            ///     my_atomic_op(atomic.as_ptr());
1018            /// }
1019            /// # }
1020            /// ```
1021            #[inline]
1022            pub const fn as_ptr(&self) -> *mut $int_type {
1023                self.0.as_ptr()
1024            }
1025        }
1026    }
1027}
1028
1029atomic_int! {
1030    "i8",
1031    "",
1032    i8 AtomicI8
1033}
1034atomic_int! {
1035    "u8",
1036    "",
1037    u8 AtomicU8
1038}
1039atomic_int! {
1040   "i16",
1041    "",
1042    i16 AtomicI16
1043}
1044atomic_int! {
1045   "u16",
1046    "",
1047    u16 AtomicU16
1048}
1049atomic_int! {
1050    "i32",
1051    "",
1052    i32 AtomicI32
1053}
1054atomic_int! {
1055    "u32",
1056    "",
1057    u32 AtomicU32
1058}
1059atomic_int! {
1060    "i64",
1061    "",
1062    i64 AtomicI64
1063}
1064atomic_int! {
1065    "u64",
1066    "",
1067    u64 AtomicU64
1068}
1069
1070atomic_int! {
1071    "isize",
1072    "",
1073    isize AtomicIsize
1074}
1075
1076atomic_int! {
1077    "usize",
1078    "",
1079    usize AtomicUsize
1080}