1use core::fmt::Debug;
2use crate::prelude::*;
3use cfg_if::cfg_if;
4
5cfg_if!(
6 if #[cfg(feature = "loom")] {
7 use loom::sync::atomic as a;
8 pub use loom::sync::Arc;
9 } else {
10 use core::sync::atomic as a;
11 #[cfg(feature = "alloc")]
12 pub use alloc::sync::Arc;
13 }
14);
15pub use a::fence;
16
17pub trait Atom: Sized + Clone + Copy + Debug {
19 type Provider: From<Self> + Debug + Default;
21
22 #[doc(hidden)]
23 fn load(provider: &Self::Provider, ordering: Ordering) -> Self;
24 #[doc(hidden)]
25 fn store(provider: &Self::Provider, value: Self, ordering: Ordering);
26 #[doc(hidden)]
27 fn swap(provider: &Self::Provider, value: Self, ordering: Ordering) -> Self;
28 #[doc(hidden)]
29 fn compare_exchange(
30 provider: &Self::Provider,
31 current: Self,
32 new: Self,
33 success: Ordering,
34 failure: Ordering,
35 ) -> Result<Self, Self>;
36 #[doc(hidden)]
37 fn compare_exchange_weak(
38 provider: &Self::Provider,
39 current: Self,
40 new: Self,
41 success: Ordering,
42 failure: Ordering,
43 ) -> Result<Self, Self>;
44 #[doc(hidden)]
45 fn fetch_update<F>(
46 provider: &Self::Provider,
47 set_ordering: Ordering,
48 fetch_ordering: Ordering,
49 f: F,
50 ) -> Result<Self, Self>
51 where
52 F: FnMut(Self) -> Option<Self>;
53}
54
55pub trait BitAtom: Atom {
57 #[doc(hidden)]
58 fn fetch_and(provider: &Self::Provider, value: Self, ordering: Ordering) -> Self;
59 #[doc(hidden)]
60 fn fetch_nand(provider: &Self::Provider, value: Self, ordering: Ordering) -> Self;
61 #[doc(hidden)]
65 fn fetch_or(provider: &Self::Provider, value: Self, ordering: Ordering) -> Self;
66 #[doc(hidden)]
67 fn fetch_xor(provider: &Self::Provider, value: Self, ordering: Ordering) -> Self;
68}
69
70pub trait IntAtom: Atom {
72 #[doc(hidden)]
73 fn fetch_add(provider: &Self::Provider, value: Self, ordering: Ordering) -> Self;
74 #[doc(hidden)]
75 fn fetch_sub(provider: &Self::Provider, value: Self, ordering: Ordering) -> Self;
76 #[doc(hidden)]
77 fn fetch_min(provider: &Self::Provider, value: Self, ordering: Ordering) -> Self;
78 #[doc(hidden)]
79 fn fetch_max(provider: &Self::Provider, value: Self, ordering: Ordering) -> Self;
80}
81
82macro_rules! or_def {
83 ($value:tt or $default:tt) => {
84 $value
85 };
86 (or $default:tt) => {
87 $default
88 };
89}
90
91macro_rules! atom_impl {
92 ($atom:ty => $provider:ident $length:literal) => {
93 #[cfg(target_has_atomic = $length)]
94 use a::$provider;
95
96 #[cfg(target_has_atomic = $length)]
97 impl Atom for $atom {
98 type Provider = $provider;
99
100 fn load(provider: &$provider, ordering: Ordering) -> Self {
101 provider.load(ordering)
102 }
103
104 fn store(provider: &$provider, value: Self, ordering: Ordering) {
105 provider.store(value, ordering)
106 }
107
108 fn swap(provider: &$provider, value: Self, ordering: Ordering) -> Self {
109 provider.swap(value, ordering)
110 }
111
112 fn compare_exchange(provider: &$provider, current: Self, new: Self, success: Ordering, failure: Ordering) -> Result<Self, Self> {
113 provider.compare_exchange(current, new, success, failure)
114 }
115
116 fn compare_exchange_weak(provider: &$provider, current: Self, new: Self, success: Ordering, failure: Ordering) -> Result<Self, Self> {
117 provider.compare_exchange_weak(current, new, success, failure)
118 }
119
120 fn fetch_update<F>(
121 provider: &$provider,
122 set_ordering: Ordering,
123 fetch_ordering: Ordering,
124 mut f: F,
125 ) -> Result<Self, Self>
126 where
127 F: FnMut(Self) -> Option<Self>
128 {
129 provider.fetch_update(set_ordering, fetch_ordering, |value| f(value))
130 }
131 }
132 };
133 ($atom:ty => $provider:ident $length:literal bit) => {
134 atom_impl!($atom => $provider $length);
135
136 #[cfg(target_has_atomic = $length)]
137 impl BitAtom for $atom {
138 fn fetch_and(provider: &$provider, value: Self, ordering: Ordering) -> Self {
139 provider.fetch_and(value, ordering)
140 }
141
142 fn fetch_nand(provider: &$provider, value: Self, ordering: Ordering) -> Self {
143 provider.fetch_nand(value, ordering)
144 }
145
146 fn fetch_or(provider: &$provider, value: Self, ordering: Ordering) -> Self {
147 provider.fetch_or(value, ordering)
148 }
149
150 fn fetch_xor(provider: &$provider, value: Self, ordering: Ordering) -> Self {
151 provider.fetch_xor(value, ordering)
152 }
153 }
154 };
155 ($atom:ty => $provider:ident $length:literal int) => {
156 atom_impl!($atom => $provider $length bit);
157
158 #[cfg(target_has_atomic = $length)]
159 impl IntAtom for $atom {
160 fn fetch_add(provider: &$provider, value: Self, ordering: Ordering) -> Self {
161 provider.fetch_add(value, ordering)
162 }
163
164 fn fetch_sub(provider: &$provider, value: Self, ordering: Ordering) -> Self {
165 provider.fetch_sub(value, ordering)
166 }
167
168 fn fetch_min(provider: &$provider, value: Self, ordering: Ordering) -> Self {
169 provider.fetch_min(value, ordering)
170 }
171
172 fn fetch_max(provider: &$provider, value: Self, ordering: Ordering) -> Self {
173 provider.fetch_max(value, ordering)
174 }
175 }
176 };
177}
178
179macro_rules! atom_impls {
180 ($($atom:ty => $provider:ident $length:literal $($s:ident)?;)+) => {
181 $(
182 atom_impl!($atom => $provider $length $($s)?);
183 )+
184 };
185}
186
187atom_impls!(
188 bool => AtomicBool "8" bit;
189 u8 => AtomicU8 "8" int;
190 u16 => AtomicU16 "16" int;
191 u32 => AtomicU32 "32" int;
192 u64 => AtomicU64 "64" int;
193 usize => AtomicUsize "ptr" int;
195 i8 => AtomicI8 "8" int;
196 i16 => AtomicI16 "16" int;
197 i32 => AtomicI32 "32" int;
198 i64 => AtomicI64 "64" int;
199 isize => AtomicIsize "ptr" int;
201);