1#![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
69pub trait Atomic {
71 type Type;
73
74 fn new(v: Self::Type) -> Self;
76
77 #[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 #[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 fn load(&self, order: Ordering) -> Self::Type;
126
127 fn store(&self, val: Self::Type, order: Ordering);
141
142 fn swap(&self, val: Self::Type, order: Ordering) -> Self::Type;
156
157 #[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 #[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 #[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 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 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 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 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 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#[cfg(any(feature = "atomic_as_ptr", feature = "since_1_70_0"))]
308pub trait AsPtr: Atomic {
309 fn as_ptr(&self) -> *mut Self::Type;
328}
329
330#[cfg(all(
332 any(feature = "atomic_from_ptr", feature = "since_1_75_0"),
333 not(feature = "loom_atomics")
334))]
335pub trait FromPtr: Atomic {
336 unsafe fn from_ptr<'a>(ptr: *mut Self::Type) -> &'a Self;
347}
348
349#[cfg(feature = "atomic_from_mut")]
350pub trait FromMut: Atomic
352where
353 Self: Sized,
354{
355 fn from_mut(v: &mut Self::Type) -> &mut Self;
370
371 fn from_mut_slice(v: &mut [Self::Type]) -> &mut [Self];
389
390 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}