atomic_traits/
lib.rs

1//! The traits for generic atomic operations
2//!
3//! # Compatibility
4//!
5//! The crate is tested for rustc 1.34 and greater.
6//!
7//! # Example
8//!
9//! ```
10//! # extern crate num_traits;
11//! # extern crate atomic_traits;
12//! use std::sync::atomic::{AtomicUsize, Ordering};
13//!
14//! use num_traits::One;
15//! use atomic_traits::{Atomic, NumOps, fetch};
16//! # use atomic_traits::fetch::{Add, Sub};
17//!
18//! #[derive(Debug, Default)]
19//! pub struct RefCnt<T>(T);
20//!
21//! impl<T> RefCnt<T>
22//! where
23//!     T: Atomic + NumOps + Default,
24//!     <T as Atomic>::Type: One
25//! {
26//!     pub fn inc(&self) -> <T as Atomic>::Type {
27//!         self.0.fetch_add(<T as Atomic>::Type::one(), Ordering::Acquire)
28//!     }
29//!
30//!     pub fn dec(&self) -> <T as Atomic>::Type {
31//!         self.0.fetch_sub(<T as Atomic>::Type::one(), Ordering::Release)
32//!     }
33//!
34//!     pub fn val(&self) -> <T as Atomic>::Type {
35//!         self.0.load(Ordering::SeqCst)
36//!     }
37//! }
38//!
39//! # fn main() {
40//! let refcnt = RefCnt::<AtomicUsize>::default();
41//!
42//! assert_eq!(refcnt.inc(), 0);
43//! assert_eq!(refcnt.dec(), 1);
44//! assert_eq!(refcnt.val(), 0);
45//! # }
46//! ```
47#![no_std]
48#![deny(missing_docs)]
49#![cfg_attr(feature = "atomic_bool_fetch_not", feature(atomic_bool_fetch_not))]
50#![cfg_attr(feature = "atomic_from_mut", feature(atomic_from_mut))]
51
52#[macro_use]
53extern crate cfg_if;
54
55cfg_if! {
56    if #[cfg(doctest)] {
57        #[macro_use]
58        extern crate doc_comment;
59
60        #[cfg(doctest)]
61        doc_comment!(include_str!("../README.md"));
62    }
63}
64
65use core::sync::atomic::*;
66
67pub mod fetch;
68
69/// Generic atomic types
70pub trait Atomic {
71    /// The underlying type
72    type Type;
73
74    /// Creates a new atomic type.
75    fn new(v: Self::Type) -> Self;
76
77    /// Returns a mutable reference to the underlying type.
78    ///
79    /// # Examples
80    ///
81    /// ```
82    /// use std::sync::atomic::{AtomicBool, Ordering};
83    /// use atomic_traits::Atomic;
84    ///
85    /// let mut some_bool = AtomicBool::new(true);
86    /// assert_eq!(*Atomic::get_mut(&mut some_bool), true);
87    /// *Atomic::get_mut(&mut some_bool) = false;
88    /// assert_eq!(Atomic::load(&some_bool, Ordering::SeqCst), false);
89    /// ```
90    #[cfg(all(
91        any(feature = "atomic_access", feature = "since_1_15_0"),
92        not(feature = "loom_atomics")
93    ))]
94    fn get_mut(&mut self) -> &mut Self::Type;
95
96    /// Consumes the atomic and returns the contained value.
97    ///
98    /// # Examples
99    ///
100    /// ```
101    /// use std::sync::atomic::AtomicBool;
102    /// use atomic_traits::Atomic;
103    ///
104    /// let some_bool = AtomicBool::new(true);
105    /// assert_eq!(Atomic::into_inner(some_bool), true);
106    /// ```
107    #[cfg(all(
108        any(feature = "atomic_access", feature = "since_1_15_0"),
109        not(feature = "loom_atomics")
110    ))]
111    fn into_inner(self) -> Self::Type;
112
113    /// Loads a value from the atomic type.
114    ///
115    /// # Examples
116    ///
117    /// ```
118    /// use std::sync::atomic::{AtomicBool, Ordering};
119    /// use atomic_traits::Atomic;
120    ///
121    /// let some_bool = AtomicBool::new(true);
122    ///
123    /// assert_eq!(Atomic::load(&some_bool, Ordering::Relaxed), true);
124    /// ```
125    fn load(&self, order: Ordering) -> Self::Type;
126
127    /// Stores a value into the atomic type.
128    ///
129    /// # Examples
130    ///
131    /// ```
132    /// use std::sync::atomic::{AtomicBool, Ordering};
133    /// use atomic_traits::Atomic;
134    ///
135    /// let some_bool = AtomicBool::new(true);
136    ///
137    /// Atomic::store(&some_bool, false, Ordering::Relaxed);
138    /// assert_eq!(Atomic::load(&some_bool, Ordering::Relaxed), false);
139    /// ```
140    fn store(&self, val: Self::Type, order: Ordering);
141
142    /// Stores a value into the atomic type, returning the previous value.
143    ///
144    /// # Examples
145    ///
146    /// ```
147    /// use std::sync::atomic::{AtomicBool, Ordering};
148    /// use atomic_traits::Atomic;
149    ///
150    /// let some_bool = AtomicBool::new(true);
151    ///
152    /// assert_eq!(Atomic::swap(&some_bool, false, Ordering::Relaxed), true);
153    /// assert_eq!(Atomic::load(&some_bool, Ordering::Relaxed), false);
154    /// ```
155    fn swap(&self, val: Self::Type, order: Ordering) -> Self::Type;
156
157    /// Stores a value into the atomic type if the current value is the same as the `current` value.
158    ///
159    /// The return value is always the previous value. If it is equal to `current`, then the value was updated.
160    ///
161    /// # Examples
162    ///
163    /// ```
164    /// use std::sync::atomic::{AtomicBool, Ordering};
165    /// use atomic_traits::Atomic;
166    ///
167    /// let some_bool = AtomicBool::new(true);
168    ///
169    /// assert_eq!(Atomic::compare_and_swap(&some_bool, true, false, Ordering::Relaxed), true);
170    /// assert_eq!(Atomic::load(&some_bool, Ordering::Relaxed), false);
171    ///
172    /// assert_eq!(Atomic::compare_and_swap(&some_bool, true, true, Ordering::Relaxed), false);
173    /// assert_eq!(Atomic::load(&some_bool, Ordering::Relaxed), false);
174    /// ```
175    #[cfg_attr(
176        feature = "since_1_50_0",
177        deprecated = "Use `compare_exchange` or `compare_exchange_weak` instead"
178    )]
179    fn compare_and_swap(&self, current: Self::Type, new: Self::Type, order: Ordering)
180        -> Self::Type;
181
182    /// Stores a value into the atomic type if the current value is the same as the `current` value.
183    ///
184    /// The return value is a result indicating whether the new value was written and containing the previous value.
185    /// On success this value is guaranteed to be equal to `current`.
186    ///
187    /// # Examples
188    ///
189    /// ```
190    /// use std::sync::atomic::{AtomicBool, Ordering};
191    /// use atomic_traits::Atomic;
192    ///
193    /// let some_bool = AtomicBool::new(true);
194    ///
195    /// assert_eq!(Atomic::compare_exchange(&some_bool,
196    ///                                      true,
197    ///                                      false,
198    ///                                      Ordering::Acquire,
199    ///                                      Ordering::Relaxed),
200    ///            Ok(true));
201    /// assert_eq!(Atomic::load(&some_bool, Ordering::Relaxed), false);
202    ///
203    /// assert_eq!(Atomic::compare_exchange(&some_bool,
204    ///                                     true,
205    ///                                     true,
206    ///                                     Ordering::SeqCst,
207    ///                                     Ordering::Acquire),
208    ///            Err(false));
209    /// assert_eq!(Atomic::load(&some_bool, Ordering::Relaxed), false);
210    /// ```
211    #[cfg(any(feature = "extended_compare_and_swap", feature = "since_1_10_0"))]
212    fn compare_exchange(
213        &self,
214        current: Self::Type,
215        new: Self::Type,
216        success: Ordering,
217        failure: Ordering,
218    ) -> Result<Self::Type, Self::Type>;
219
220    /// Stores a value into the atomic type if the current value is the same as the current value.
221    ///
222    /// Unlike `compare_exchange`, this function is allowed to spuriously fail even when the comparison succeeds,
223    /// which can result in more efficient code on some platforms.
224    /// The return value is a result indicating whether the new value was written and containing the previous value.
225    ///
226    /// # Examples
227    ///
228    /// ```
229    /// use std::sync::atomic::{AtomicBool, Ordering};
230    /// use atomic_traits::Atomic;
231    ///
232    /// let val = AtomicBool::new(false);
233    ///
234    /// let new = true;
235    /// let mut old = Atomic::load(&val, Ordering::Relaxed);
236    /// loop {
237    ///     match Atomic::compare_exchange_weak(&val, old, new, Ordering::SeqCst, Ordering::Relaxed) {
238    ///         Ok(_) => break,
239    ///         Err(x) => old = x,
240    ///     }
241    /// }
242    /// ```
243    #[cfg(any(feature = "extended_compare_and_swap", feature = "since_1_10_0"))]
244    fn compare_exchange_weak(
245        &self,
246        current: Self::Type,
247        new: Self::Type,
248        success: Ordering,
249        failure: Ordering,
250    ) -> Result<Self::Type, Self::Type>;
251}
252
253cfg_if! {
254    if #[cfg(all(any(feature = "atomic_nand", feature = "since_1_27_0"), not(feature = "loom_atomics")))] {
255        /// The trait for types implementing atomic bitwise operations
256        pub trait Bitwise: Atomic
257            + fetch::And<Type = <Self as Atomic>::Type>
258            + fetch::Nand<Type = <Self as Atomic>::Type>
259            + fetch::Or<Type = <Self as Atomic>::Type>
260            + fetch::Xor<Type = <Self as Atomic>::Type>
261        {
262        }
263    } else {
264        /// The trait for types implementing atomic bitwise operations
265        pub trait Bitwise: Atomic
266            + fetch::And<Type = <Self as Atomic>::Type>
267            + fetch::Or<Type = <Self as Atomic>::Type>
268            + fetch::Xor<Type = <Self as Atomic>::Type>
269        {
270        }
271    }
272}
273
274cfg_if! {
275    if #[cfg(feature = "loom_atomics")] {
276        /// The trait for types implementing atomic numeric operations
277        pub trait NumOps:
278            Atomic
279            + fetch::Add<Type = <Self as Atomic>::Type>
280            + fetch::Sub<Type = <Self as Atomic>::Type>
281            + fetch::Update<Type = <Self as Atomic>::Type>
282        {
283        }
284    } else if #[cfg(feature = "since_1_45_0")] {
285        /// The trait for types implementing atomic numeric operations
286        pub trait NumOps:
287            Atomic
288            + fetch::Add<Type = <Self as Atomic>::Type>
289            + fetch::Sub<Type = <Self as Atomic>::Type>
290            + fetch::Update<Type = <Self as Atomic>::Type>
291            + fetch::Max<Type = <Self as Atomic>::Type>
292            + fetch::Min<Type = <Self as Atomic>::Type>
293        {
294        }
295    } else {
296        /// The trait for types implementing atomic numeric operations
297        pub trait NumOps:
298            Atomic
299            + fetch::Add<Type = <Self as Atomic>::Type>
300            + fetch::Sub<Type = <Self as Atomic>::Type>
301        {
302        }
303    }
304}
305
306/// Returns a mutable pointer to the underlying type.
307#[cfg(any(feature = "atomic_as_ptr", feature = "since_1_70_0"))]
308pub trait AsPtr: Atomic {
309    /// Returns a mutable pointer to the underlying type.
310    ///
311    /// # Examples
312    ///
313    /// ```ignore (extern-declaration)
314    /// # fn main() {
315    /// use std::sync::atomic::AtomicBool;
316    /// use atomic_traits::Atomic;
317    ///
318    /// extern "C" {
319    ///     fn my_atomic_op(arg: *mut bool);
320    /// }
321    ///
322    /// let mut atomic = AtomicBool::new(true);
323    /// unsafe {
324    ///     my_atomic_op(Atomic::as_ptr(&atomic));
325    /// }
326    /// # }    
327    fn as_ptr(&self) -> *mut Self::Type;
328}
329
330/// Creates a new atomic type from a pointer.
331#[cfg(all(
332    any(feature = "atomic_from_ptr", feature = "since_1_75_0"),
333    not(feature = "loom_atomics")
334))]
335pub trait FromPtr: Atomic {
336    /// Creates a new atomic type from a pointer.
337    ///     
338    /// # Safety
339    ///
340    /// * `ptr` must be aligned to `align_of::<Self>()` (note that on some platforms this can
341    ///   be bigger than `align_of::<Self::Type>()`).
342    /// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`.
343    /// * You must adhere to the [Memory model for atomic accesses]. In particular, it is not
344    ///   allowed to mix atomic and non-atomic accesses, or atomic accesses of different sizes,
345    ///   without synchronization.
346    unsafe fn from_ptr<'a>(ptr: *mut Self::Type) -> &'a Self;
347}
348
349#[cfg(feature = "atomic_from_mut")]
350/// Get atomic access to mutable atomic type or slice.
351pub trait FromMut: Atomic
352where
353    Self: Sized,
354{
355    /// Get atomic access to an atomic type.
356    ///
357    /// # Examples
358    ///
359    /// ```
360    /// #![feature(atomic_from_mut)]
361    /// use std::sync::atomic::{AtomicBool, Ordering};
362    /// use atomic_traits::Atomic;
363    ///
364    /// let mut some_bool = true;
365    /// let a = <AtomicBool as Atomic>::from_mut(&mut some_bool);
366    /// Atomic::store(&a, false, Ordering::Relaxed);
367    /// assert_eq!(some_bool, false);
368    /// ```    
369    fn from_mut(v: &mut Self::Type) -> &mut Self;
370
371    /// Get atomic access to a `&mut [Self::Type]` slice.
372    ///
373    /// # Examples
374    ///
375    /// ```
376    /// #![feature(atomic_from_mut)]
377    /// use std::sync::atomic::{AtomicBool, Ordering};
378    ///
379    /// let mut some_bools = [false; 10];
380    /// let a = &*AtomicBool::from_mut_slice(&mut some_bools);
381    /// std::thread::scope(|s| {
382    ///     for i in 0..a.len() {
383    ///         s.spawn(move || a[i].store(true, Ordering::Relaxed));
384    ///     }
385    /// });
386    /// assert_eq!(some_bools, [true; 10]);
387    /// ```    
388    fn from_mut_slice(v: &mut [Self::Type]) -> &mut [Self];
389
390    /// Get non-atomic access to a `&mut [Self]` slice.
391    ///
392    /// This is safe because the mutable reference guarantees that no other threads are
393    /// concurrently accessing the atomic data.
394    ///
395    /// # Examples
396    ///
397    /// ```
398    /// #![feature(atomic_from_mut, inline_const)]
399    /// use std::sync::atomic::{AtomicBool, Ordering};
400    /// use atomic_traits::Atomic;
401    ///
402    /// let mut some_bools = [const { AtomicBool::new(false) }; 10];
403    ///
404    /// let view: &mut [bool] = <AtomicBool as Atomic>::get_mut_slice(&mut some_bools);
405    /// assert_eq!(view, [false; 10]);
406    /// view[..5].copy_from_slice(&[true; 5]);
407    ///
408    /// std::thread::scope(|s| {
409    ///     for t in &some_bools[..5] {
410    ///         s.spawn(move || assert_eq!(t.load(Ordering::Relaxed), true));
411    ///     }
412    ///
413    ///     for f in &some_bools[5..] {
414    ///         s.spawn(move || assert_eq!(f.load(Ordering::Relaxed), false));
415    ///     }
416    /// });
417    /// ```    
418    fn get_mut_slice(this: &mut [Self]) -> &mut [Self::Type];
419}
420
421macro_rules! impl_atomic {
422    ($atomic:path : $primitive:ty ; $( $rest:tt ),*) => {
423        impl_atomic!(__impl atomic $atomic : $primitive);
424
425        $(
426            impl_atomic!(__impl $rest $atomic : $primitive);
427        )*
428
429    };
430    ($atomic:ident < $param:ident > ; $( $rest:tt ),*) => {
431        impl<$param> Atomic for $atomic <$param> {
432            type Type = *mut $param;
433
434            impl_atomic!(__impl atomic_methods $atomic);
435        }
436
437        $(
438            impl_atomic!(__impl $rest $atomic <$param>);
439        )*
440    };
441    (__loom $atomic:ident < $param:ident >) => {
442        impl<$param> Atomic for loom::sync::atomic::$atomic <$param> {
443            type Type = *mut $param;
444
445            impl_atomic!(__impl atomic_methods loom::sync::atomic::$atomic);
446        }
447    };
448    (__impl atomic $atomic:path : $primitive:ty) => {
449        impl Atomic for $atomic {
450            type Type = $primitive;
451
452            impl_atomic!(__impl atomic_methods $atomic);
453        }
454    };
455
456    (__impl atomic_methods $atomic:path) => {
457        #[inline(always)]
458        fn new(v: Self::Type) -> Self {
459            Self::new(v)
460        }
461
462        #[cfg(all(
463            any(feature = "atomic_access", feature = "since_1_15_0"),
464            not(feature = "loom_atomics")
465        ))]
466        #[inline(always)]
467        fn get_mut(&mut self) -> &mut Self::Type {
468            Self::get_mut(self)
469        }
470
471        #[cfg(all(
472            any(feature = "atomic_access", feature = "since_1_15_0"),
473            not(feature = "loom_atomics")
474        ))]
475        #[inline(always)]
476        fn into_inner(self) -> Self::Type {
477            Self::into_inner(self)
478        }
479
480        #[inline(always)]
481        fn load(&self, order: Ordering) -> Self::Type {
482            Self::load(self, order)
483        }
484
485        #[inline(always)]
486        fn store(&self, val: Self::Type, order: Ordering) {
487            Self::store(self, val, order)
488        }
489
490        #[inline(always)]
491        fn swap(&self, val: Self::Type, order: Ordering) -> Self::Type {
492            Self::swap(self, val, order)
493        }
494
495        #[inline(always)]
496        fn compare_and_swap(
497            &self,
498            current: Self::Type,
499            new: Self::Type,
500            order: Ordering,
501        ) -> Self::Type {
502            #[cfg_attr(feature = "since_1_50_0", allow(deprecated))]
503            Self::compare_and_swap(self, current, new, order)
504        }
505
506        #[cfg(any(feature = "extended_compare_and_swap", feature = "since_1_10_0"))]
507        #[inline(always)]
508        fn compare_exchange(
509            &self,
510            current: Self::Type,
511            new: Self::Type,
512            success: Ordering,
513            failure: Ordering,
514        ) -> Result<Self::Type, Self::Type> {
515            Self::compare_exchange(self, current, new, success, failure)
516        }
517
518        #[cfg(any(feature = "extended_compare_and_swap", feature = "since_1_10_0"))]
519        #[inline(always)]
520        fn compare_exchange_weak(
521            &self,
522            current: Self::Type,
523            new: Self::Type,
524            success: Ordering,
525            failure: Ordering,
526        ) -> Result<Self::Type, Self::Type> {
527            Self::compare_exchange_weak(self, current, new, success, failure)
528        }
529    };
530
531    (__impl bitwise $atomic:path : $primitive:ty) => {
532        impl Bitwise for $atomic {}
533
534        impl $crate::fetch::And for $atomic {
535            type Type = $primitive;
536
537            #[inline(always)]
538            fn fetch_and(&self, val: Self::Type, order: Ordering) -> Self::Type {
539                Self::fetch_and(self, val, order)
540            }
541        }
542
543        #[cfg(any(feature = "atomic_nand", feature = "since_1_27_0"))]
544        impl $crate::fetch::Nand for $atomic {
545            type Type = $primitive;
546
547            #[inline(always)]
548            fn fetch_nand(&self, val: Self::Type, order: Ordering) -> Self::Type {
549                Self::fetch_nand(self, val, order)
550            }
551        }
552
553        impl $crate::fetch::Or for $atomic {
554            type Type = $primitive;
555
556            #[inline(always)]
557            fn fetch_or(&self, val: Self::Type, order: Ordering) -> Self::Type {
558                Self::fetch_or(self, val, order)
559            }
560        }
561
562        impl $crate::fetch::Xor for $atomic {
563            type Type = $primitive;
564
565            #[inline(always)]
566            fn fetch_xor(&self, val: Self::Type, order: Ordering) -> Self::Type {
567                Self::fetch_xor(self, val, order)
568            }
569        }
570    };
571
572    (__impl numops $atomic:path : $primitive:ty) => {
573        impl NumOps for $atomic {}
574
575        impl $crate::fetch::Add for $atomic {
576            type Type = $primitive;
577
578            #[inline(always)]
579            fn fetch_add(&self, val: Self::Type, order: Ordering) -> Self::Type {
580                Self::fetch_add(self, val, order)
581            }
582        }
583
584        impl $crate::fetch::Sub for $atomic {
585            type Type = $primitive;
586
587            #[inline(always)]
588            fn fetch_sub(&self, val: Self::Type, order: Ordering) -> Self::Type {
589                Self::fetch_sub(self, val, order)
590            }
591        }
592
593        #[cfg(any(feature = "since_1_45_0", feature = "loom_atomics"))]
594        impl_atomic!(__impl fetch_update $atomic : $primitive);
595
596        impl_atomic!(__impl min_max $atomic : $primitive);
597    };
598
599    (__impl fetch_update $atomic:ident < $param:ident >) => {
600        impl < $param > $crate::fetch::Update for $atomic < $param > {
601            type Type = *mut $param;
602
603            #[inline(always)]
604            fn fetch_update<F>(
605                &self,
606                fetch_order: Ordering,
607                set_order: Ordering,
608                f: F,
609            ) -> Result<Self::Type, Self::Type>
610            where
611                F: FnMut(Self::Type) -> Option<Self::Type> {
612                Self::fetch_update(self, fetch_order, set_order, f)
613            }
614        }
615    };
616
617    (__impl fetch_update $atomic:path : $primitive:ty) => {
618        impl $crate::fetch::Update for $atomic {
619            type Type = $primitive;
620
621            #[inline(always)]
622            fn fetch_update<F>(
623                &self,
624                fetch_order: Ordering,
625                set_order: Ordering,
626                f: F,
627            ) -> Result<Self::Type, Self::Type>
628            where
629                F: FnMut(Self::Type) -> Option<Self::Type> {
630                Self::fetch_update(self, fetch_order, set_order, f)
631            }
632        }
633    };
634
635    (__impl fetch_not $atomic:path : $primitive:ty) => {
636        #[cfg(feature = "atomic_bool_fetch_not")]
637        impl $crate::fetch::Not for $atomic {
638            type Type = $primitive;
639
640            #[inline(always)]
641            fn fetch_not(&self, order: Ordering) -> Self::Type {
642                Self::fetch_not(self, order)
643            }
644        }
645    };
646
647    (__impl min_max $atomic:path : $primitive:ty) => {
648        cfg_if! {
649            if #[cfg(any(feature = "atomic_min_max", feature = "since_1_45_0"))] {
650                impl $crate::fetch::Max for $atomic {
651                    type Type = $primitive;
652
653                    #[inline(always)]
654                    fn fetch_max(&self, val: Self::Type, order: Ordering) -> Self::Type {
655                        Self::fetch_max(self, val, order)
656                    }
657                }
658
659                impl $crate::fetch::Min for $atomic {
660                    type Type = $primitive;
661
662                    #[inline(always)]
663                    fn fetch_min(&self, val: Self::Type, order: Ordering) -> Self::Type {
664                        Self::fetch_min(self, val, order)
665                    }
666                }
667            }
668        }
669    };
670
671    (__impl from_ptr $atomic:path : $primitive:ty) => {
672        #[cfg(all(
673            any(feature = "atomic_from_ptr", feature = "since_1_75_0"),
674            not(feature = "loom_atomics")
675        ))]
676        impl FromPtr for $atomic {
677            unsafe fn from_ptr<'a>(ptr: *mut Self::Type) -> &'a Self {
678                Self::from_ptr(ptr)
679            }
680        }
681    };
682
683    (__impl from_ptr $atomic:ident < $param:ident >) => {
684        #[cfg(all(
685            any(feature = "atomic_from_ptr", feature = "since_1_75_0"),
686            not(feature = "loom_atomics")
687        ))]
688        impl < $param > FromPtr for $atomic < $param > {
689            unsafe fn from_ptr<'a>(ptr: *mut Self::Type) -> &'a Self {
690                Self::from_ptr(ptr)
691            }
692        }
693    };
694
695    (__impl as_ptr $atomic:path : $primitive:ty) => {
696        #[cfg(any(feature = "atomic_as_ptr", feature = "since_1_70_0"))]
697        impl AsPtr for $atomic {
698            #[inline(always)]
699            fn as_ptr(&self) -> *mut Self::Type {
700                Self::as_ptr(&self)
701            }
702        }
703    };
704
705    (__impl as_ptr $atomic:ident < $param:ident >) => {
706        #[cfg(any(feature = "atomic_as_ptr", feature = "since_1_70_0"))]
707        impl < $param > AsPtr for $atomic < $param > {
708            #[inline(always)]
709            fn as_ptr(&self) -> *mut Self::Type {
710                Self::as_ptr(&self)
711            }
712        }
713    };
714
715    (__impl from_mut $atomic:path : $primitive:ty) => {
716        #[cfg(feature = "atomic_from_mut")]
717        impl FromMut for $atomic
718        where
719            Self: Sized,
720        {
721            #[inline(always)]
722            fn from_mut(v: &mut Self::Type) -> &mut Self {
723                Self::from_mut(v)
724            }
725
726            #[inline(always)]
727            fn from_mut_slice(v: &mut [Self::Type]) -> &mut [Self] {
728                Self::from_mut_slice(v)
729            }
730
731            #[inline(always)]
732            fn get_mut_slice(this: &mut [Self]) -> &mut [Self::Type] {
733                Self::get_mut_slice(this)
734            }
735        }
736    };
737
738    (__impl from_mut $atomic:ident < $param:ident >) => {
739        #[cfg(feature = "atomic_from_mut")]
740        impl < $param > FromMut for $atomic < $param >
741        where
742            Self: Sized,
743        {
744            #[inline(always)]
745            fn from_mut(v: &mut Self::Type) -> &mut Self {
746                Self::from_mut(v)
747            }
748
749            #[inline(always)]
750            fn from_mut_slice(v: &mut [Self::Type]) -> &mut [Self] {
751                Self::from_mut_slice(v)
752            }
753
754            #[inline(always)]
755            fn get_mut_slice(this: &mut [Self]) -> &mut [Self::Type] {
756                Self::get_mut_slice(this)
757            }
758        }
759    };
760}
761
762cfg_if! {
763    if #[cfg(any(
764        all(any(feature = "use_target_has_atomic", feature = "since_1_60_0"), target_has_atomic = "8"),
765        all(
766            not(any(feature = "use_target_has_atomic", feature = "since_1_60_0")),
767            any(
768                target_pointer_width = "16",
769                target_pointer_width = "32",
770                target_pointer_width = "64"
771            )
772        )
773    ))] {
774        impl_atomic!(AtomicBool: bool; bitwise, fetch_not, as_ptr, from_mut);
775
776        #[cfg(any(feature = "since_1_53_0", feature = "loom_atomics"))]
777        impl_atomic!(__impl fetch_update AtomicBool : bool);
778    }
779}
780
781cfg_if! {
782    if #[cfg(any(not(any(feature = "use_target_has_atomic", feature = "since_1_60_0")), target_has_atomic = "ptr"))] {
783        impl_atomic!(AtomicIsize: isize; bitwise, numops, as_ptr, from_ptr, from_mut);
784        impl_atomic!(AtomicUsize: usize; bitwise, numops, as_ptr, from_ptr, from_mut);
785        impl_atomic!(AtomicPtr<T>; as_ptr, from_ptr, from_mut);
786
787        #[cfg(any(feature = "since_1_53_0", feature = "loom_atomics"))]
788        impl_atomic!(__impl fetch_update AtomicPtr<T>);
789    }
790}
791
792#[cfg(any(feature = "integer_atomics", feature = "since_1_34_0"))]
793mod integer_atomics {
794    use super::*;
795
796    cfg_if! {
797        if #[cfg(any(
798            all(any(feature = "use_target_has_atomic", feature = "since_1_60_0"), target_has_atomic = "8"),
799            all(
800                not(any(feature = "use_target_has_atomic", feature = "since_1_60_0")),
801                any(
802                    target_pointer_width = "16",
803                    target_pointer_width = "32",
804                    target_pointer_width = "64"
805                )
806            )
807        ))] {
808            impl_atomic!(AtomicI8: i8; bitwise, numops, as_ptr, from_ptr, from_mut);
809            impl_atomic!(AtomicU8: u8; bitwise, numops, as_ptr, from_ptr, from_mut);
810        }
811    }
812
813    cfg_if! {
814        if #[cfg(any(
815            all(any(feature = "use_target_has_atomic", feature = "since_1_60_0"), target_has_atomic = "16"),
816            all(
817                not(any(feature = "use_target_has_atomic", feature = "since_1_60_0")),
818                any(
819                    target_pointer_width = "16",
820                    target_pointer_width = "32",
821                    target_pointer_width = "64"
822                )
823            )
824        ))] {
825            impl_atomic!(AtomicI16: i16; bitwise, numops, as_ptr, from_ptr, from_mut);
826            impl_atomic!(AtomicU16: u16; bitwise, numops, as_ptr, from_ptr, from_mut);
827        }
828    }
829
830    cfg_if! {
831        if #[cfg(any(
832            all(any(feature = "use_target_has_atomic", feature = "since_1_60_0"), target_has_atomic = "32"),
833            all(
834                not(any(feature = "use_target_has_atomic", feature = "since_1_60_0")),
835                any(target_pointer_width = "32", target_pointer_width = "64")
836            )
837        ))] {
838            impl_atomic!(AtomicI32: i32; bitwise, numops, as_ptr, from_ptr, from_mut);
839            impl_atomic!(AtomicU32: u32; bitwise, numops, as_ptr, from_ptr, from_mut);
840        }
841    }
842
843    cfg_if! {
844        if #[cfg(any(
845            all(any(feature = "use_target_has_atomic", feature = "since_1_60_0"), target_has_atomic = "64"),
846            all(not(any(feature = "use_target_has_atomic", feature = "since_1_60_0")), target_pointer_width = "64")
847        ))] {
848            impl_atomic!(AtomicI64: i64; bitwise, numops, as_ptr, from_ptr, from_mut);
849            impl_atomic!(AtomicU64: u64; bitwise, numops, as_ptr, from_ptr, from_mut);
850        }
851    }
852}
853
854#[cfg(feature = "loom_atomics")]
855mod loom_atomics {
856    extern crate loom;
857
858    use super::*;
859
860    cfg_if! {
861        if #[cfg(any(
862            all(any(feature = "use_target_has_atomic", feature = "since_1_60_0"), target_has_atomic = "8"),
863            all(
864                not(any(feature = "use_target_has_atomic", feature = "since_1_60_0")),
865                any(
866                    target_pointer_width = "16",
867                    target_pointer_width = "32",
868                    target_pointer_width = "64"
869                )
870            )
871        ))] {
872            impl_atomic!(loom::sync::atomic::AtomicBool: bool; bitwise);
873        }
874    }
875
876    cfg_if! {
877        if #[cfg(any(not(any(feature = "use_target_has_atomic", feature = "since_1_60_0")), target_has_atomic = "ptr"))] {
878            impl_atomic!(loom::sync::atomic::AtomicIsize: isize; bitwise, numops);
879            impl_atomic!(loom::sync::atomic::AtomicUsize: usize; bitwise, numops);
880
881            impl_atomic!(__loom AtomicPtr<T>);
882        }
883    }
884
885    cfg_if! {
886        if #[cfg(any(
887            all(any(feature = "use_target_has_atomic", feature = "since_1_60_0"), target_has_atomic = "8"),
888            all(
889                not(any(feature = "use_target_has_atomic", feature = "since_1_60_0")),
890                any(
891                    target_pointer_width = "16",
892                    target_pointer_width = "32",
893                    target_pointer_width = "64"
894                )
895            )
896        ))] {
897            impl_atomic!(loom::sync::atomic::AtomicI8: i8; bitwise, numops);
898            impl_atomic!(loom::sync::atomic::AtomicU8: u8; bitwise, numops);
899        }
900    }
901
902    cfg_if! {
903        if #[cfg(any(
904            all(any(feature = "use_target_has_atomic", feature = "since_1_60_0"), target_has_atomic = "16"),
905            all(
906                not(any(feature = "use_target_has_atomic", feature = "since_1_60_0")),
907                any(
908                    target_pointer_width = "16",
909                    target_pointer_width = "32",
910                    target_pointer_width = "64"
911                )
912            )
913        ))] {
914            impl_atomic!(loom::sync::atomic::AtomicI16: i16; bitwise, numops);
915            impl_atomic!(loom::sync::atomic::AtomicU16: u16; bitwise, numops);
916        }
917    }
918
919    cfg_if! {
920        if #[cfg(any(
921            all(any(feature = "use_target_has_atomic", feature = "since_1_60_0"), target_has_atomic = "32"),
922            all(
923                not(any(feature = "use_target_has_atomic", feature = "since_1_60_0")),
924                any(target_pointer_width = "32", target_pointer_width = "64")
925            )
926        ))] {
927            impl_atomic!(loom::sync::atomic::AtomicI32: i32; bitwise, numops);
928            impl_atomic!(loom::sync::atomic::AtomicU32: u32; bitwise, numops);
929        }
930    }
931
932    cfg_if! {
933        if #[cfg(any(
934            all(any(feature = "use_target_has_atomic", feature = "since_1_60_0"), target_has_atomic = "64"),
935            all(not(any(feature = "use_target_has_atomic", feature = "since_1_60_0")), target_pointer_width = "64")
936        ))] {
937            impl_atomic!(loom::sync::atomic::AtomicI64: i64; bitwise, numops);
938            impl_atomic!(loom::sync::atomic::AtomicU64: u64; bitwise, numops);
939        }
940    }
941}