Skip to main content

portable_atomic/
lib.rs

1// SPDX-License-Identifier: Apache-2.0 OR MIT
2
3/*!
4<!-- Note: Document from sync-markdown-to-rustdoc:start through sync-markdown-to-rustdoc:end
5     is synchronized from README.md. Any changes to that range are not preserved. -->
6<!-- tidy:sync-markdown-to-rustdoc:start -->
7
8Portable atomic types including support for 128-bit atomics, atomic float, etc.
9
10- Provide all atomic integer types (`Atomic{I,U}{8,16,32,64}`) for all targets that can use atomic CAS. (i.e., all targets that can use `std`, and most no-std targets)
11- Provide `AtomicI128` and `AtomicU128`.
12- Provide `AtomicF32` and `AtomicF64`. ([optional, requires the `float` feature](#optional-features-float))
13- Provide `AtomicF16` and `AtomicF128` for [unstable `f16` and `f128`](https://github.com/rust-lang/rust/issues/116909). ([optional, requires the `float` feature and unstable cfgs](#optional-features-float))
14- Provide atomic load/store for targets where atomic is not available at all in the standard library. (RISC-V without A-extension, MSP430, AVR)
15- Provide atomic CAS for targets where atomic CAS is not available in the standard library. (thumbv6m, pre-v6 Arm, RISC-V without A-extension, MSP430, AVR, Xtensa, etc.) (always enabled for MSP430 and AVR, [optional](#optional-features-critical-section) otherwise)
16- Make features that require newer compilers, such as [`fetch_{max,min}`](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicUsize.html#method.fetch_max), [`fetch_update`](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicUsize.html#method.fetch_update), [`as_ptr`](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicUsize.html#method.as_ptr), [`from_ptr`](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicUsize.html#method.from_ptr), [`AtomicBool::fetch_not`](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicBool.html#method.fetch_not), [`AtomicPtr::fetch_*`](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicPtr.html#method.fetch_and), and [stronger CAS failure ordering](https://github.com/rust-lang/rust/pull/98383) available on Rust 1.34+.
17- Provide workaround for bugs in the standard library's atomic-related APIs, such as [rust-lang/compiler-builtins#1234], [rust-lang/rust#100650], `fence`/`compiler_fence` on MSP430 that cause LLVM error, etc.
18
19<!-- TODO:
20- mention Atomic{I,U}*::fetch_neg, Atomic{I*,U*,Ptr}::bit_*, etc.
21- mention optimizations not available in the standard library's equivalents
22-->
23
24portable-atomic version of `std::sync::Arc` and `std::task::Wake` is provided by the [portable-atomic-util] crate.
25
26## Usage
27
28Add this to your `Cargo.toml`:
29
30```toml
31[dependencies]
32portable-atomic = "1"
33```
34
35The default features are mainly for users who use atomics larger than the pointer width.
36If you don't need them, disabling the default features may reduce code size and compile time slightly.
37
38```toml
39[dependencies]
40portable-atomic = { version = "1", default-features = false }
41```
42
43If your crate supports no-std environment and requires atomic CAS, enabling the `require-cas` feature will allow the portable-atomic to display a [helpful error message](https://github.com/taiki-e/portable-atomic/pull/100) to users on targets requiring additional action on the user side to provide atomic CAS.
44
45```toml
46[dependencies]
47portable-atomic = { version = "1.3", default-features = false, features = ["require-cas"] }
48```
49
50(Since 1.8, portable-atomic can display a [helpful error message](https://github.com/taiki-e/portable-atomic/pull/181) even without the `require-cas` feature when the rustc version is 1.78+. However, the `require-cas` feature also allows rejecting builds at an earlier stage, we recommend enabling it unless enabling it causes [problems](https://github.com/matklad/once_cell/pull/267).)
51
52## 128-bit atomics support
53
54Native 128-bit atomic operations are available on x86_64 (Rust 1.59+), AArch64 (Rust 1.59+), riscv64 (Rust 1.59+), Arm64EC (Rust 1.84+), s390x (Rust 1.84+), and powerpc64 (Rust 1.95+), otherwise the fallback implementation is used.
55
56On x86_64, even if `cmpxchg16b` is not available at compile-time (Note: `cmpxchg16b` target feature is enabled by default only on Apple, Windows (except Windows 7), and Fuchsia targets), run-time detection checks whether `cmpxchg16b` is available. If `cmpxchg16b` is not available at either compile-time or run-time detection, the fallback implementation is used. See also [`portable_atomic_no_outline_atomics`](#optional-cfg-no-outline-atomics) cfg.
57
58They are usually implemented using inline assembly, and when using Miri or ThreadSanitizer that do not support inline assembly, core intrinsics are used instead of inline assembly if possible.
59
60See the [`atomic128` module's readme](https://github.com/taiki-e/portable-atomic/blob/HEAD/src/imp/atomic128/README.md) for details.
61
62## <a name="optional-features"></a><a name="optional-cfg"></a>Optional features/cfgs
63
64portable-atomic provides features and cfgs to allow enabling specific APIs and customizing its behavior.
65
66Some options have both a feature and a cfg. When both exist, it indicates that the feature does not follow Cargo's recommendation that [features should be additive](https://doc.rust-lang.org/nightly/cargo/reference/features.html#feature-unification). Therefore, the maintainer's recommendation is to use cfg instead of feature. However, in the embedded ecosystem, it is very common to use features in such places, so these options provide both so you can choose based on your preference.
67
68<details>
69<summary>How to enable cfg (click to show)</summary>
70
71One of the ways to enable cfg is to set [rustflags in the cargo config](https://doc.rust-lang.org/cargo/reference/config.html#targettriplerustflags):
72
73```toml
74# .cargo/config.toml
75[target.<target>]
76rustflags = ["--cfg", "portable_atomic_unsafe_assume_single_core"]
77```
78
79Or set environment variable:
80
81```sh
82RUSTFLAGS="--cfg portable_atomic_unsafe_assume_single_core" cargo ...
83```
84
85</details>
86
87- <a name="optional-features-fallback"></a>**`fallback` feature** *(enabled by default)*<br>
88  Enable fallback implementations.
89
90  This enables atomic types with larger than the width supported by atomic instructions available on the current target. If the current target [supports 128-bit atomics](#128-bit-atomics-support), this is no-op.
91
92  This uses fallback implementation that using global locks by default. The following features/cfgs change this behavior:
93  - [`unsafe-assume-single-core` feature / `portable_atomic_unsafe_assume_single_core` cfg](#optional-features-unsafe-assume-single-core): Use fallback implementations that disabling interrupts instead of using global locks.
94    - If your target is single-core and calling interrupt disable instructions is safe, this is a safer and more efficient option.
95  - [`unsafe-assume-privileged` feature / `portable_atomic_unsafe_assume_privileged` cfg](#optional-features-unsafe-assume-privileged): Use fallback implementations that using global locks with disabling interrupts.
96    - If your target is multi-core and calling interrupt disable instructions is safe, this is a safer option.
97
98- <a name="optional-features-float"></a>**`float` feature**<br>
99  Provide `AtomicF{32,64}`.
100
101  If you want atomic types for unstable float types ([`f16` and `f128`](https://github.com/rust-lang/rust/issues/116909)), enable unstable cfg (`portable_atomic_unstable_f16` cfg for `AtomicF16`, `portable_atomic_unstable_f128` cfg for `AtomicF128`, [there is no possibility that both feature and cfg will be provided for unstable options.](https://github.com/taiki-e/portable-atomic/pull/200#issuecomment-2682252991)).
102
103<div class="rustdoc-alert rustdoc-alert-note">
104
105> **ⓘ Note**
106>
107> - Atomic float's `fetch_{add,sub,min,max}` are usually implemented using CAS loops, which can be slower than equivalent operations of atomic integers. As an exception, AArch64 with FEAT_LSFE and GPU targets have atomic float instructions and we use them on AArch64 when `lsfe` target feature is available at compile-time. We [plan to use atomic float instructions for GPU targets as well in the future.](https://github.com/taiki-e/portable-atomic/issues/34)
108> - Unstable cfgs are outside of the normal semver guarantees and minor or patch versions of portable-atomic may make breaking changes to them at any time.
109
110</div>
111
112- <a name="optional-features-std"></a>**`std` feature**<br>
113  Use `std`.
114
115- <a name="optional-features-require-cas"></a>**`require-cas` feature**<br>
116  Emit compile error if atomic CAS is not available. See [Usage](#usage) section for usage of this feature.
117
118- <a name="optional-features-serde"></a>**`serde` feature**<br>
119  Implement `serde::{Serialize,Deserialize}` for atomic types.
120
121  Note:
122  - The MSRV when this feature is enabled depends on the MSRV of [serde].
123
124- <a name="optional-features-critical-section"></a>**`critical-section` feature**<br>
125  Use [critical-section] to provide atomic CAS for targets where atomic CAS is not available in the standard library.
126
127  `critical-section` support is useful to get atomic CAS when the [`unsafe-assume-single-core` feature (or `portable_atomic_unsafe_assume_single_core` cfg)](#optional-features-unsafe-assume-single-core) can't be used,
128  such as multi-core targets, unprivileged code running under some RTOS, or environments where disabling interrupts
129  needs extra care due to e.g. real-time requirements.
130
131<div class="rustdoc-alert rustdoc-alert-note">
132
133> **ⓘ Note**
134>
135> - When enabling this feature, you should provide a suitable critical section implementation for the current target, see the [critical-section] documentation for details on how to do so.
136> - With this feature, critical sections are taken for all atomic operations, while with `unsafe-assume-single-core` feature [some operations](https://github.com/taiki-e/portable-atomic/blob/HEAD/src/imp/interrupt/README.md#no-disable-interrupts) don't require disabling interrupts. Therefore, for better performance, if all the `critical-section` implementation for your target does is disable interrupts, prefer using `unsafe-assume-single-core` feature (or `portable_atomic_unsafe_assume_single_core` cfg) instead.
137> - It is usually **discouraged** to always enable this feature in libraries that depend on `portable-atomic`.
138>
139>   Enabling this feature will prevent the end user from having the chance to take advantage of other (potentially) efficient implementations (implementations provided by `unsafe-assume-single-core` feature mentioned above, implementation proposed in [#60], etc.). Also, targets that are currently unsupported may be supported in the future.
140>
141>   The recommended approach for libraries is to leave it up to the end user whether or not to enable this feature. (However, it may make sense to enable this feature by default for libraries specific to a platform where other implementations are known not to work.)
142>
143>   See also [this comment](https://github.com/matklad/once_cell/issues/264#issuecomment-2352654806).
144>
145>   As an example, the end-user's `Cargo.toml` that uses a crate that provides a critical-section implementation and a crate that depends on portable-atomic as an option would be expected to look like this:
146>
147>   ```toml
148>   [dependencies]
149>   portable-atomic = { version = "1", default-features = false, features = ["critical-section"] }
150>   crate-provides-critical-section-impl = "..."
151>   crate-uses-portable-atomic-as-feature = { version = "...", features = ["portable-atomic"] }
152>   ```
153>
154> - Enabling both this feature and `unsafe-assume-single-core` feature (or `portable_atomic_unsafe_assume_single_core` cfg) will result in a compile error.
155> - Enabling both this feature and `unsafe-assume-privileged` feature (or `portable_atomic_unsafe_assume_privileged` cfg) will result in a compile error.
156> - The MSRV when this feature is enabled depends on the MSRV of [critical-section].
157
158</div>
159
160- <a name="optional-features-unsafe-assume-single-core"></a><a name="optional-cfg-unsafe-assume-single-core"></a>**`unsafe-assume-single-core` feature / `portable_atomic_unsafe_assume_single_core` cfg**<br>
161  Assume that the target is single-core and privileged instructions required to disable interrupts are available.
162
163  - When this feature/cfg is enabled, this crate provides atomic CAS for targets where atomic CAS is not available in the standard library by disabling interrupts.
164  - When both this feature/cfg and enabled-by-default `fallback` feature is enabled, this crate provides atomic types with larger than the width supported by native instructions by disabling interrupts.
165
166<div class="rustdoc-alert rustdoc-alert-warning">
167
168> **⚠ Warning**
169>
170> This feature/cfg is `unsafe`, and note the following safety requirements:
171> - Enabling this feature/cfg for multi-core systems is always **unsound**.
172>
173> - This uses privileged instructions to disable interrupts, so it usually doesn't work on unprivileged mode.
174>
175>   Enabling this feature/cfg in an environment where privileged instructions are not available, or if the instructions used are not sufficient to disable interrupts in the system, it is also usually considered **unsound**, although the details are system-dependent.
176>
177>   The following are known cases:
178>   - On Arm (except for M-Profile architectures), this disables only IRQs by default. For many systems (e.g., GBA) this is enough. If the system need to disable both IRQs and FIQs, you need to enable the `disable-fiq` feature (or `portable_atomic_disable_fiq` cfg) together.
179>   - On RISC-V, this generates code for machine-mode (M-mode) by default. If you enable the `s-mode` feature (or `portable_atomic_s_mode` cfg) together, this generates code for supervisor-mode (S-mode). In particular, `qemu-system-riscv*` uses [OpenSBI](https://github.com/riscv-software-src/opensbi) as the default firmware.
180
181</div>
182
183Consider using the [`unsafe-assume-privileged` feature (or `portable_atomic_unsafe_assume_privileged` cfg)](#optional-features-unsafe-assume-privileged) for multi-core systems with atomic CAS.
184
185Consider using the [`critical-section` feature](#optional-features-critical-section) for systems that cannot use this feature/cfg.
186
187See also the [`interrupt` module's readme](https://github.com/taiki-e/portable-atomic/blob/HEAD/src/imp/interrupt/README.md).
188
189<div class="rustdoc-alert rustdoc-alert-note">
190
191> **ⓘ Note**
192>
193> - It is **very strongly discouraged** to enable this feature/cfg in libraries that depend on `portable-atomic`.
194>
195>   The recommended approach for libraries is to leave it up to the end user whether or not to enable this feature/cfg. (However, it may make sense to enable this feature/cfg by default for libraries specific to a platform where it is guaranteed to always be sound, for example in a hardware abstraction layer targeting a single-core chip.)
196> - Enabling this feature/cfg for unsupported architectures will result in a compile error.
197>   - Arm, RISC-V, and Xtensa are currently supported. (Since all MSP430 and AVR are single-core, we always provide atomic CAS for them without this feature/cfg.)
198>   - Feel free to [submit an issue](https://github.com/taiki-e/portable-atomic/issues/new) if your target is not supported yet.
199> - Enabling this feature/cfg for targets where privileged instructions are obviously unavailable (e.g., Linux) will result in a compile error.
200>   - Feel free to [submit an issue](https://github.com/taiki-e/portable-atomic/issues/new) if your target supports privileged instructions but the build rejected.
201> - Enabling both this feature/cfg and `critical-section` feature will result in a compile error.
202> - When both this feature/cfg and `unsafe-assume-privileged` feature (or `portable_atomic_unsafe_assume_privileged` cfg) are enabled, this feature/cfg is preferred.
203
204</div>
205
206- <a name="optional-features-unsafe-assume-privileged"></a><a name="optional-cfg-unsafe-assume-privileged"></a>**`unsafe-assume-privileged` feature / `portable_atomic_unsafe_assume_privileged` cfg**<br>
207  Similar to `unsafe-assume-single-core` feature / `portable_atomic_unsafe_assume_single_core` cfg, but only assumes about availability of privileged instructions required to disable interrupts.
208
209  - When both this feature/cfg and enabled-by-default `fallback` feature is enabled, this crate provides atomic types with larger than the width supported by native instructions by using global locks with disabling interrupts.
210
211<div class="rustdoc-alert rustdoc-alert-warning">
212
213> **⚠ Warning**
214>
215> This feature/cfg is `unsafe`, and except for being sound in multi-core systems, this has the same safety requirements as [`unsafe-assume-single-core` feature / `portable_atomic_unsafe_assume_single_core` cfg](#optional-features-unsafe-assume-single-core).
216
217</div>
218
219<div class="rustdoc-alert rustdoc-alert-note">
220
221> **ⓘ Note**
222>
223> - It is **very strongly discouraged** to enable this feature/cfg in libraries that depend on `portable-atomic`.
224>
225>   The recommended approach for libraries is to leave it up to the end user whether or not to enable this feature/cfg. (However, it may make sense to enable this feature/cfg by default for libraries specific to a platform where it is guaranteed to always be sound, for example in a hardware abstraction layer.)
226> - Enabling this feature/cfg for unsupported targets will result in a compile error.
227>   - This requires atomic CAS (`cfg(target_has_atomic = "ptr")` or `cfg_no_atomic_cas!`).
228>   - Arm, RISC-V, and Xtensa are currently supported.
229>   - Feel free to [submit an issue](https://github.com/taiki-e/portable-atomic/issues/new) if your target is not supported yet.
230> - Enabling this feature/cfg for targets where privileged instructions are obviously unavailable (e.g., Linux) will result in a compile error.
231>   - Feel free to [submit an issue](https://github.com/taiki-e/portable-atomic/issues/new) if your target supports privileged instructions but the build rejected.
232> - Enabling both this feature/cfg and `critical-section` feature will result in a compile error.
233> - When both this feature/cfg and `unsafe-assume-single-core` feature (or `portable_atomic_unsafe_assume_single_core` cfg) are enabled, `unsafe-assume-single-core` is preferred.
234
235</div>
236
237- <a name="optional-cfg-no-outline-atomics"></a>**`portable_atomic_no_outline_atomics` cfg**<br>
238  Disable dynamic dispatching by run-time CPU feature detection.
239
240  Dynamic dispatching by run-time CPU feature detection allows maintaining support for older CPUs while using features that are not supported on older CPUs, such as CMPXCHG16B (x86_64) and FEAT_LSE/FEAT_LSE2 (AArch64).
241
242  See also the [`atomic128` module's readme](https://github.com/taiki-e/portable-atomic/blob/HEAD/src/imp/atomic128/README.md).
243
244<div class="rustdoc-alert rustdoc-alert-note">
245
246> **ⓘ Note**
247>
248> - If the required target features are enabled at compile-time, dynamic dispatching is automatically disabled and the atomic operations are inlined.
249> - This is compatible with no-std (as with all features except `std`).
250> - On some targets, run-time detection is disabled by default mainly for compatibility with incomplete build environments or support for it is experimental, and can be enabled by `portable_atomic_outline_atomics` cfg. (When both cfg are enabled, `*_no_*` cfg is preferred.)
251> - Some AArch64 targets enable LLVM's `outline-atomics` target feature by default, so if you set this cfg, you may want to disable that as well. (However, portable-atomic's outline-atomics does not depend on the compiler-rt symbols, so even if you need to disable LLVM's outline-atomics, you may not need to disable portable-atomic's outline-atomics.)
252> - Dynamic detection is currently only supported in x86_64, AArch64, Arm, RISC-V, Arm64EC, and powerpc64. Enabling this cfg for unsupported architectures will be ignored.
253
254</div>
255
256## Related Projects
257
258- [portable-atomic-util]: Synchronization primitives built with portable-atomic. This provides portable-atomic version of `std::sync::Arc` and `std::task::Wake`.
259- [atomic-maybe-uninit]: Atomic operations on potentially uninitialized integers.
260- [atomic-memcpy]: Byte-wise atomic memcpy.
261- [asmtest]: A library for tracking generated assemblies.
262
263[#60]: https://github.com/taiki-e/portable-atomic/issues/60
264[asmtest]: https://github.com/taiki-e/asmtest
265[atomic-maybe-uninit]: https://github.com/taiki-e/atomic-maybe-uninit
266[atomic-memcpy]: https://github.com/taiki-e/atomic-memcpy
267[critical-section]: https://github.com/rust-embedded/critical-section
268[portable-atomic-util]: https://github.com/taiki-e/portable-atomic-util
269[rust-lang/compiler-builtins#1234]: https://github.com/rust-lang/compiler-builtins/pull/1234
270[rust-lang/rust#100650]: https://github.com/rust-lang/rust/issues/100650
271[serde]: https://github.com/serde-rs/serde
272
273<!-- tidy:sync-markdown-to-rustdoc:end -->
274*/
275
276#![no_std]
277#![doc(test(
278    no_crate_inject,
279    attr(
280        deny(warnings, rust_2018_idioms, single_use_lifetimes),
281        allow(dead_code, unused_variables)
282    )
283))]
284#![cfg_attr(not(portable_atomic_no_unsafe_op_in_unsafe_fn), warn(unsafe_op_in_unsafe_fn))] // unsafe_op_in_unsafe_fn requires Rust 1.52
285#![cfg_attr(portable_atomic_no_unsafe_op_in_unsafe_fn, allow(unused_unsafe))]
286#![warn(
287    // Lints that may help when writing public library.
288    missing_debug_implementations,
289    // missing_docs,
290    clippy::alloc_instead_of_core,
291    clippy::exhaustive_enums,
292    clippy::exhaustive_structs,
293    clippy::impl_trait_in_params,
294    clippy::std_instead_of_alloc,
295    clippy::std_instead_of_core,
296    clippy::missing_inline_in_public_items,
297    // Code outside of cfg(feature = "float") shouldn't use float.
298    clippy::float_arithmetic,
299)]
300#![cfg_attr(not(portable_atomic_no_asm), warn(missing_docs))] // module-level #![allow(missing_docs)] doesn't work for macros on old rustc
301#![cfg_attr(portable_atomic_no_strict_provenance, allow(unstable_name_collisions))]
302#![allow(
303    clippy::inline_always,
304    clippy::manual_assert_eq,
305    clippy::unreadable_literal,
306    clippy::used_underscore_items
307)]
308// asm_experimental_arch
309// AVR, MSP430, and Xtensa are tier 3 platforms and require nightly anyway.
310// On tier 2 platforms (currently N/A), we use cfg set by build script to
311// determine whether this feature is available or not.
312#![cfg_attr(
313    all(
314        not(portable_atomic_no_asm),
315        any(
316            all(target_arch = "avr", not(feature = "critical-section")),
317            target_arch = "msp430",
318            all(
319                target_arch = "xtensa",
320                any(
321                    portable_atomic_unsafe_assume_single_core,
322                    portable_atomic_unsafe_assume_privileged,
323                ),
324            ),
325        ),
326    ),
327    feature(asm_experimental_arch)
328)]
329// f16/f128
330// cfg is unstable and explicitly enabled by the user
331#![cfg_attr(
332    any(portable_atomic_unstable_f16, portable_atomic_unstable_f128),
333    allow(unused_features)
334)]
335#![cfg_attr(all(portable_atomic_unstable_f16, feature = "float"), feature(f16))]
336#![cfg_attr(all(portable_atomic_unstable_f128, feature = "float"), feature(f128))]
337// Old nightly only
338// These features are already stabilized or have already been removed from compilers,
339// and can safely be enabled for old nightly as long as version detection works.
340// - cfg(target_has_atomic)
341// - asm! on AArch64, Arm, RISC-V, x86, x86_64, Arm64EC, s390x, PowerPC64
342// - llvm_asm! on AVR (tier 3) and MSP430 (tier 3)
343// - #[instruction_set] on non-Linux/Android pre-v6 Arm (tier 3)
344// This also helps us test that our assembly code works with the minimum external
345// LLVM version of the first rustc version that inline assembly stabilized.
346#![cfg_attr(portable_atomic_unstable_cfg_target_has_atomic, feature(cfg_target_has_atomic))]
347#![cfg_attr(
348    all(
349        portable_atomic_unstable_asm,
350        any(
351            target_arch = "aarch64",
352            target_arch = "arm",
353            target_arch = "riscv32",
354            target_arch = "riscv64",
355            target_arch = "x86",
356            target_arch = "x86_64",
357        ),
358    ),
359    feature(asm)
360)]
361#![cfg_attr(
362    all(
363        portable_atomic_unstable_asm_experimental_arch,
364        any(target_arch = "arm64ec", target_arch = "s390x", target_arch = "powerpc64"),
365    ),
366    feature(asm_experimental_arch)
367)]
368#![cfg_attr(
369    all(any(target_arch = "avr", target_arch = "msp430"), portable_atomic_no_asm),
370    feature(llvm_asm)
371)]
372#![cfg_attr(
373    all(
374        target_arch = "arm",
375        portable_atomic_unstable_isa_attribute,
376        any(portable_atomic_unsafe_assume_single_core, portable_atomic_unsafe_assume_privileged),
377        not(any(target_feature = "v7", portable_atomic_target_feature = "v7")),
378        not(any(target_feature = "mclass", portable_atomic_target_feature = "mclass")),
379    ),
380    feature(isa_attribute)
381)]
382// Miri and/or ThreadSanitizer only
383// They do not support inline assembly, so we need to use unstable features instead.
384// Since they require nightly compilers anyway, we can use the unstable features.
385// This is not an ideal situation, but it is still better than always using lock-based
386// fallback and causing memory ordering problems to be missed by these checkers.
387#![cfg_attr(
388    all(
389        any(
390            target_arch = "aarch64",
391            target_arch = "arm64ec",
392            target_arch = "powerpc64",
393            target_arch = "s390x",
394        ),
395        any(miri, portable_atomic_sanitize_thread),
396    ),
397    allow(internal_features)
398)]
399#![cfg_attr(
400    all(
401        any(
402            target_arch = "aarch64",
403            target_arch = "arm64ec",
404            target_arch = "powerpc64",
405            target_arch = "s390x",
406        ),
407        portable_atomic_atomic_intrinsics,
408        any(miri, portable_atomic_sanitize_thread),
409    ),
410    feature(core_intrinsics)
411)]
412// docs.rs only (cfg is enabled by docs.rs, not build script)
413#![cfg_attr(docsrs, feature(doc_cfg))]
414#![cfg_attr(docsrs, doc(auto_cfg = false))]
415#![cfg_attr(
416    all(
417        portable_atomic_no_atomic_load_store,
418        not(any(
419            target_arch = "avr",
420            target_arch = "bpf",
421            target_arch = "msp430",
422            target_arch = "riscv32",
423            target_arch = "riscv64",
424            feature = "critical-section",
425            portable_atomic_unsafe_assume_single_core,
426        )),
427    ),
428    allow(unused_imports, unused_macros, clippy::unused_trait_names)
429)]
430
431#[cfg(any(test, feature = "std"))]
432extern crate std;
433
434#[macro_use]
435mod cfgs;
436#[cfg(target_pointer_width = "16")]
437pub use self::{cfg_has_atomic_16 as cfg_has_atomic_ptr, cfg_no_atomic_16 as cfg_no_atomic_ptr};
438#[cfg(target_pointer_width = "32")]
439pub use self::{cfg_has_atomic_32 as cfg_has_atomic_ptr, cfg_no_atomic_32 as cfg_no_atomic_ptr};
440#[cfg(target_pointer_width = "64")]
441pub use self::{cfg_has_atomic_64 as cfg_has_atomic_ptr, cfg_no_atomic_64 as cfg_no_atomic_ptr};
442#[cfg(target_pointer_width = "128")]
443pub use self::{cfg_has_atomic_128 as cfg_has_atomic_ptr, cfg_no_atomic_128 as cfg_no_atomic_ptr};
444
445// There are currently no 128-bit or higher builtin targets.
446// (Although some of our generic code is written with the future
447// addition of 128-bit targets in mind.)
448// Note that Rust (and C99) pointers must be at least 16-bit (i.e., 8-bit targets are impossible): https://github.com/rust-lang/rust/pull/49305
449#[cfg(not(any(
450    target_pointer_width = "16",
451    target_pointer_width = "32",
452    target_pointer_width = "64",
453)))]
454compile_error!(
455    "portable-atomic currently only supports targets with {16,32,64}-bit pointer width; \
456     if you need support for others, \
457     please submit an issue at <https://github.com/taiki-e/portable-atomic>"
458);
459
460// Reject unsupported architectures.
461#[cfg(portable_atomic_unsafe_assume_single_core)]
462#[cfg(not(any(
463    target_arch = "arm",
464    target_arch = "avr",
465    target_arch = "msp430",
466    target_arch = "riscv32",
467    target_arch = "riscv64",
468    target_arch = "xtensa",
469)))]
470compile_error!(
471    "`portable_atomic_unsafe_assume_single_core` cfg (`unsafe-assume-single-core` feature) \
472     is not supported yet on this architecture;\n\
473     if you need unsafe-assume-{single-core,privileged} support for this target,\n\
474     please submit an issue at <https://github.com/taiki-e/portable-atomic/issues/new>"
475);
476// unsafe-assume-single-core is accepted on AVR/MSP430, but
477// unsafe-assume-privileged on them is really useless on them since they are
478// always single-core, so rejected here.
479#[cfg(portable_atomic_unsafe_assume_privileged)]
480#[cfg(not(any(
481    target_arch = "arm",
482    target_arch = "riscv32",
483    target_arch = "riscv64",
484    target_arch = "xtensa",
485)))]
486compile_error!(
487    "`portable_atomic_unsafe_assume_privileged` cfg (`unsafe-assume-privileged` feature) \
488     is not supported yet on this architecture;\n\
489     if you need unsafe-assume-{single-core,privileged} support for this target,\n\
490     please submit an issue at <https://github.com/taiki-e/portable-atomic/issues/new>"
491);
492// unsafe-assume-privileged requires CAS.
493#[cfg(portable_atomic_unsafe_assume_privileged)]
494cfg_no_atomic_cas! {
495    compile_error!(
496        "`portable_atomic_unsafe_assume_privileged` cfg (`unsafe-assume-privileged` feature) \
497        requires atomic CAS"
498    );
499}
500// Reject targets where privileged instructions are obviously unavailable.
501// TODO: Some embedded OSes should probably be accepted here.
502#[cfg(any(portable_atomic_unsafe_assume_single_core, portable_atomic_unsafe_assume_privileged))]
503#[cfg(any(
504    target_arch = "arm",
505    target_arch = "avr",
506    target_arch = "msp430",
507    target_arch = "riscv32",
508    target_arch = "riscv64",
509    target_arch = "xtensa",
510))]
511#[cfg_attr(
512    portable_atomic_no_cfg_target_has_atomic,
513    cfg(all(not(portable_atomic_no_atomic_cas), not(target_os = "none")))
514)]
515#[cfg_attr(
516    not(portable_atomic_no_cfg_target_has_atomic),
517    cfg(all(target_has_atomic = "ptr", not(target_os = "none")))
518)]
519compile_error!(
520    "`portable_atomic_unsafe_assume_{single_core,privileged}` cfg (`unsafe-assume-{single-core,privileged}` feature) \
521     is not compatible with target where privileged instructions are obviously unavailable;\n\
522     if you need unsafe-assume-{single-core,privileged} support for this target,\n\
523     please submit an issue at <https://github.com/taiki-e/portable-atomic/issues/new>\n\
524     see also <https://github.com/taiki-e/portable-atomic/issues/148> for troubleshooting"
525);
526
527#[cfg(portable_atomic_outline_atomics)]
528#[cfg(not(any(
529    target_arch = "aarch64",
530    target_arch = "powerpc64",
531    target_arch = "riscv32",
532    target_arch = "riscv64",
533)))]
534compile_error!("`portable_atomic_outline_atomics` cfg does not compatible with this target");
535
536#[cfg(portable_atomic_disable_fiq)]
537#[cfg(not(all(
538    target_arch = "arm",
539    not(any(target_feature = "mclass", portable_atomic_target_feature = "mclass")),
540)))]
541compile_error!(
542    "`portable_atomic_disable_fiq` cfg (`disable-fiq` feature) is only available on Arm (except for M-Profile architectures)"
543);
544#[cfg(portable_atomic_s_mode)]
545#[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))]
546compile_error!("`portable_atomic_s_mode` cfg (`s-mode` feature) is only available on RISC-V");
547#[cfg(portable_atomic_force_amo)]
548#[cfg(not(any(target_arch = "riscv32", target_arch = "riscv64")))]
549compile_error!("`portable_atomic_force_amo` cfg (`force-amo` feature) is only available on RISC-V");
550
551#[cfg(portable_atomic_disable_fiq)]
552#[cfg(not(any(
553    portable_atomic_unsafe_assume_single_core,
554    portable_atomic_unsafe_assume_privileged,
555)))]
556compile_error!(
557    "`portable_atomic_disable_fiq` cfg (`disable-fiq` feature) may only be used together with `portable_atomic_unsafe_assume_{single_core,privileged}` cfg (`unsafe-assume-{single-core,privileged}` feature)"
558);
559#[cfg(portable_atomic_s_mode)]
560#[cfg(not(any(
561    portable_atomic_unsafe_assume_single_core,
562    portable_atomic_unsafe_assume_privileged,
563)))]
564compile_error!(
565    "`portable_atomic_s_mode` cfg (`s-mode` feature) may only be used together with `portable_atomic_unsafe_assume_{single_core,privileged}` cfg (`unsafe-assume-{single-core,privileged}` feature)"
566);
567#[cfg(portable_atomic_force_amo)]
568#[cfg(not(portable_atomic_unsafe_assume_single_core))]
569compile_error!(
570    "`portable_atomic_force_amo` cfg (`force-amo` feature) may only be used together with `portable_atomic_unsafe_assume_single_core` cfg (`unsafe-assume-single-core` feature)"
571);
572#[cfg(portable_atomic_unsafe_assume_privileged)]
573#[cfg(not(feature = "fallback"))]
574compile_error!(
575    "`portable_atomic_unsafe_assume_privileged` cfg (`unsafe-assume-privileged` feature) may only be used together with `fallback` feature"
576);
577
578#[cfg(all(
579    any(portable_atomic_unsafe_assume_single_core, portable_atomic_unsafe_assume_privileged),
580    feature = "critical-section"
581))]
582compile_error!(
583    "you may not enable `critical-section` feature and `portable_atomic_unsafe_assume_{single_core,privileged}` cfg (`unsafe-assume-{single-core,privileged}` feature) at the same time"
584);
585
586#[cfg(feature = "require-cas")]
587#[cfg_attr(
588    portable_atomic_no_cfg_target_has_atomic,
589    cfg(not(any(
590        not(portable_atomic_no_atomic_cas),
591        target_arch = "avr",
592        target_arch = "msp430",
593        feature = "critical-section",
594        portable_atomic_unsafe_assume_single_core,
595    )))
596)]
597#[cfg_attr(
598    not(portable_atomic_no_cfg_target_has_atomic),
599    cfg(not(any(
600        target_has_atomic = "ptr",
601        target_arch = "avr",
602        target_arch = "msp430",
603        feature = "critical-section",
604        portable_atomic_unsafe_assume_single_core,
605    )))
606)]
607compile_error!(
608    "dependents require atomic CAS but not available on this target by default;\n\
609    consider enabling one of the `critical-section` feature or `unsafe-assume-single-core` feature (or `portable_atomic_unsafe_assume_single_core` cfg).\n\
610    see <https://docs.rs/portable-atomic/latest/portable_atomic/#optional-features> for more."
611);
612
613#[macro_use]
614mod utils;
615
616#[cfg(test)]
617#[macro_use]
618mod tests;
619
620#[doc(no_inline)]
621pub use core::sync::atomic::Ordering;
622
623cfg_sel!({
624    // LLVM doesn't support fence/compiler_fence for MSP430.
625    #[cfg(target_arch = "msp430")]
626    {
627        pub use self::imp::msp430::compiler_fence;
628    }
629    #[cfg(else)]
630    {
631        pub use core::sync::atomic::compiler_fence;
632    }
633});
634cfg_sel!({
635    // LLVM doesn't support fence/compiler_fence for MSP430.
636    #[cfg(target_arch = "msp430")]
637    {
638        pub use self::imp::msp430::fence;
639    }
640    // We have optimized fence for x86.
641    // Miri and Sanitizer do not support inline assembly.
642    #[cfg(all(
643        not(doc),
644        any(target_arch = "x86", target_arch = "x86_64"),
645        not(any(miri, portable_atomic_sanitize_thread)),
646        any(not(portable_atomic_no_asm), portable_atomic_unstable_asm),
647    ))]
648    {
649        pub use self::imp::x86::fence;
650    }
651    // We have optimized fence for pre-v6 ARM Linux/Android.
652    // Miri and Sanitizer do not go through __sync_synchronize.
653    #[cfg(all(
654        not(doc),
655        target_arch = "arm",
656        not(any(miri, portable_atomic_sanitize_thread)),
657        any(target_os = "linux", target_os = "android"),
658        not(any(target_feature = "v6", portable_atomic_target_feature = "v6")),
659    ))]
660    {
661        pub use self::imp::arm_linux::fence;
662    }
663    #[cfg(else)]
664    {
665        pub use core::sync::atomic::fence;
666    }
667});
668
669mod imp;
670
671pub mod hint {
672    //! Re-export of the [`core::hint`] module.
673    //!
674    //! The only difference from the [`core::hint`] module is that [`spin_loop`]
675    //! is available in all rust versions that this crate supports.
676    //!
677    //! ```
678    //! use portable_atomic::hint;
679    //!
680    //! hint::spin_loop();
681    //! ```
682
683    #[doc(no_inline)]
684    pub use core::hint::*;
685
686    /// Emits a machine instruction to signal the processor that it is running in
687    /// a busy-wait spin-loop ("spin lock").
688    ///
689    /// Upon receiving the spin-loop signal the processor can optimize its behavior by,
690    /// for example, saving power or switching hyper-threads.
691    ///
692    /// This function is different from [`thread::yield_now`] which directly
693    /// yields to the system's scheduler, whereas `spin_loop` does not interact
694    /// with the operating system.
695    ///
696    /// A common use case for `spin_loop` is implementing bounded optimistic
697    /// spinning in a CAS loop in synchronization primitives. To avoid problems
698    /// like priority inversion, it is strongly recommended that the spin loop is
699    /// terminated after a finite amount of iterations and an appropriate blocking
700    /// syscall is made.
701    ///
702    /// **Note:** On platforms that do not support receiving spin-loop hints this
703    /// function does not do anything at all.
704    ///
705    /// [`thread::yield_now`]: https://doc.rust-lang.org/std/thread/fn.yield_now.html
706    #[inline]
707    pub fn spin_loop() {
708        #[allow(deprecated)]
709        core::sync::atomic::spin_loop_hint();
710    }
711}
712
713#[cfg(doc)]
714use core::sync::atomic::Ordering::{AcqRel, Acquire, Relaxed, Release, SeqCst};
715use core::{fmt, ptr};
716
717cfg_has_atomic_8! {
718/// A boolean type which can be safely shared between threads.
719///
720/// This type has the same in-memory representation as a [`bool`].
721///
722/// If the compiler and the platform support atomic loads and stores of `u8`,
723/// this type is a wrapper for the standard library's
724/// [`AtomicBool`](core::sync::atomic::AtomicBool). If the platform supports it
725/// but the compiler does not, atomic operations are implemented using inline
726/// assembly.
727#[repr(C, align(1))]
728pub struct AtomicBool {
729    v: core::cell::UnsafeCell<u8>,
730}
731
732impl Default for AtomicBool {
733    /// Creates an `AtomicBool` initialized to `false`.
734    #[inline]
735    fn default() -> Self {
736        Self::new(false)
737    }
738}
739
740impl From<bool> for AtomicBool {
741    /// Converts a `bool` into an `AtomicBool`.
742    #[inline]
743    fn from(b: bool) -> Self {
744        Self::new(b)
745    }
746}
747
748// Send is implicitly implemented.
749// SAFETY: any data races are prevented by disabling interrupts or
750// atomic intrinsics (see module-level comments).
751unsafe impl Sync for AtomicBool {}
752
753// UnwindSafe is implicitly implemented.
754#[cfg(not(portable_atomic_no_core_unwind_safe))]
755impl core::panic::RefUnwindSafe for AtomicBool {}
756#[cfg(all(portable_atomic_no_core_unwind_safe, feature = "std"))]
757impl std::panic::RefUnwindSafe for AtomicBool {}
758
759impl_debug_and_serde!(AtomicBool);
760
761impl AtomicBool {
762    /// Creates a new `AtomicBool`.
763    ///
764    /// # Examples
765    ///
766    /// ```
767    /// use portable_atomic::AtomicBool;
768    ///
769    /// let atomic_true = AtomicBool::new(true);
770    /// let atomic_false = AtomicBool::new(false);
771    /// ```
772    #[inline]
773    #[must_use]
774    pub const fn new(v: bool) -> Self {
775        static_assert_layout!(AtomicBool, bool);
776        Self { v: core::cell::UnsafeCell::new(v as u8) }
777    }
778
779    // TODO: update docs based on https://github.com/rust-lang/rust/pull/116762
780    const_fn! {
781        const_if: #[cfg(not(portable_atomic_no_const_raw_ptr_deref))];
782        /// Creates a new `AtomicBool` from a pointer.
783        ///
784        /// This is `const fn` on Rust 1.58+.
785        ///
786        /// # Safety
787        ///
788        /// * `ptr` must be aligned to `align_of::<AtomicBool>()` (note that on some platforms this can
789        ///   be bigger than `align_of::<bool>()`).
790        /// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`.
791        /// * If this atomic type is [lock-free](Self::is_lock_free), non-atomic accesses to the value
792        ///   behind `ptr` must have a happens-before relationship with atomic accesses via the returned
793        ///   value (or vice-versa).
794        ///   * In other words, time periods where the value is accessed atomically may not overlap
795        ///     with periods where the value is accessed non-atomically.
796        ///   * This requirement is trivially satisfied if `ptr` is never used non-atomically for the
797        ///     duration of lifetime `'a`. Most use cases should be able to follow this guideline.
798        ///   * This requirement is also trivially satisfied if all accesses (atomic or not) are done
799        ///     from the same thread.
800        /// * If this atomic type is *not* lock-free:
801        ///   * Any accesses to the value behind `ptr` must have a happens-before relationship
802        ///     with accesses via the returned value (or vice-versa).
803        ///   * Any concurrent accesses to the value behind `ptr` for the duration of lifetime `'a` must
804        ///     be compatible with operations performed by this atomic type.
805        /// * This method must not be used to create overlapping or mixed-size atomic accesses, as
806        ///   these are not supported by the memory model.
807        ///
808        /// [valid]: core::ptr#safety
809        #[inline]
810        #[must_use]
811        pub const unsafe fn from_ptr<'a>(ptr: *mut bool) -> &'a Self {
812            #[allow(clippy::cast_ptr_alignment)]
813            // SAFETY: guaranteed by the caller
814            unsafe { &*(ptr as *mut Self as *const Self) }
815        }
816    }
817
818    /// Returns `true` if operations on values of this type are lock-free.
819    ///
820    /// If the compiler or the platform doesn't support the necessary
821    /// atomic instructions, global locks for every potentially
822    /// concurrent atomic operation will be used.
823    ///
824    /// This function is guaranteed to always return the same result.
825    ///
826    /// # Examples
827    ///
828    /// ```
829    /// use portable_atomic::AtomicBool;
830    ///
831    /// let is_lock_free = AtomicBool::is_lock_free();
832    /// ```
833    #[inline]
834    #[must_use]
835    pub fn is_lock_free() -> bool {
836        imp::AtomicU8::is_lock_free()
837    }
838
839    /// Returns `true` if operations on values of this type are lock-free.
840    ///
841    /// If the compiler or the platform doesn't support the necessary
842    /// atomic instructions, global locks for every potentially
843    /// concurrent atomic operation will be used.
844    ///
845    /// **Note:** If the atomic operation relies on dynamic CPU feature detection,
846    /// this type may be lock-free even if the function returns false.
847    ///
848    /// # Examples
849    ///
850    /// ```
851    /// use portable_atomic::AtomicBool;
852    ///
853    /// const IS_ALWAYS_LOCK_FREE: bool = AtomicBool::is_always_lock_free();
854    /// ```
855    #[inline]
856    #[must_use]
857    pub const fn is_always_lock_free() -> bool {
858        imp::AtomicU8::IS_ALWAYS_LOCK_FREE
859    }
860    #[cfg(test)]
861    const IS_ALWAYS_LOCK_FREE: bool = Self::is_always_lock_free();
862
863    const_fn! {
864        const_if: #[cfg(not(portable_atomic_no_const_mut_refs))];
865        /// Returns a mutable reference to the underlying [`bool`].
866        ///
867        /// This is safe because the mutable reference guarantees that no other threads are
868        /// concurrently accessing the atomic data.
869        ///
870        /// This is `const fn` on Rust 1.83+.
871        ///
872        /// # Examples
873        ///
874        /// ```
875        /// use portable_atomic::{AtomicBool, Ordering};
876        ///
877        /// let mut some_bool = AtomicBool::new(true);
878        /// assert_eq!(*some_bool.get_mut(), true);
879        /// *some_bool.get_mut() = false;
880        /// assert_eq!(some_bool.load(Ordering::SeqCst), false);
881        /// ```
882        #[inline]
883        pub const fn get_mut(&mut self) -> &mut bool {
884            // SAFETY: the mutable reference guarantees unique ownership.
885            unsafe { &mut *self.as_ptr() }
886        }
887    }
888
889    // TODO: Add from_mut/get_mut_slice/from_mut_slice once it is stable on std atomic types.
890    // https://github.com/rust-lang/rust/issues/76314
891
892    const_fn! {
893        const_if: #[cfg(not(portable_atomic_no_const_transmute))];
894        /// Consumes the atomic and returns the contained value.
895        ///
896        /// This is safe because passing `self` by value guarantees that no other threads are
897        /// concurrently accessing the atomic data.
898        ///
899        /// This is `const fn` on Rust 1.56+.
900        ///
901        /// # Examples
902        ///
903        /// ```
904        /// use portable_atomic::AtomicBool;
905        ///
906        /// let some_bool = AtomicBool::new(true);
907        /// assert_eq!(some_bool.into_inner(), true);
908        /// ```
909        #[inline]
910        pub const fn into_inner(self) -> bool {
911            // SAFETY: AtomicBool and u8 have the same size and in-memory representations,
912            // so they can be safely transmuted.
913            // (const UnsafeCell::into_inner is unstable)
914            unsafe { core::mem::transmute::<AtomicBool, u8>(self) != 0 }
915        }
916    }
917
918    /// Loads a value from the bool.
919    ///
920    /// `load` takes an [`Ordering`] argument which describes the memory ordering
921    /// of this operation. Possible values are [`SeqCst`], [`Acquire`] and [`Relaxed`].
922    ///
923    /// # Panics
924    ///
925    /// Panics if `order` is [`Release`] or [`AcqRel`].
926    ///
927    /// # Examples
928    ///
929    /// ```
930    /// use portable_atomic::{AtomicBool, Ordering};
931    ///
932    /// let some_bool = AtomicBool::new(true);
933    ///
934    /// assert_eq!(some_bool.load(Ordering::Relaxed), true);
935    /// ```
936    #[inline]
937    #[cfg_attr(
938        any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri),
939        track_caller
940    )]
941    pub fn load(&self, order: Ordering) -> bool {
942        self.as_atomic_u8().load(order) != 0
943    }
944
945    /// Stores a value into the bool.
946    ///
947    /// `store` takes an [`Ordering`] argument which describes the memory ordering
948    /// of this operation. Possible values are [`SeqCst`], [`Release`] and [`Relaxed`].
949    ///
950    /// # Panics
951    ///
952    /// Panics if `order` is [`Acquire`] or [`AcqRel`].
953    ///
954    /// # Examples
955    ///
956    /// ```
957    /// use portable_atomic::{AtomicBool, Ordering};
958    ///
959    /// let some_bool = AtomicBool::new(true);
960    ///
961    /// some_bool.store(false, Ordering::Relaxed);
962    /// assert_eq!(some_bool.load(Ordering::Relaxed), false);
963    /// ```
964    #[inline]
965    #[cfg_attr(
966        any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri),
967        track_caller
968    )]
969    pub fn store(&self, val: bool, order: Ordering) {
970        self.as_atomic_u8().store(val as u8, order);
971    }
972
973    cfg_has_atomic_cas_or_amo32! {
974    /// Stores a value into the bool, returning the previous value.
975    ///
976    /// `swap` takes an [`Ordering`] argument which describes the memory ordering
977    /// of this operation. All ordering modes are possible. Note that using
978    /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
979    /// using [`Release`] makes the load part [`Relaxed`].
980    ///
981    /// # Examples
982    ///
983    /// ```
984    /// use portable_atomic::{AtomicBool, Ordering};
985    ///
986    /// let some_bool = AtomicBool::new(true);
987    ///
988    /// assert_eq!(some_bool.swap(false, Ordering::Relaxed), true);
989    /// assert_eq!(some_bool.load(Ordering::Relaxed), false);
990    /// ```
991    #[inline]
992    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
993    pub fn swap(&self, val: bool, order: Ordering) -> bool {
994        #[cfg(any(
995            target_arch = "riscv32",
996            target_arch = "riscv64",
997            target_arch = "loongarch32",
998            target_arch = "loongarch64",
999        ))]
1000        {
1001            // See https://github.com/rust-lang/rust/pull/114034 for details.
1002            // https://github.com/rust-lang/rust/blob/1.84.0/library/core/src/sync/atomic.rs#L249
1003            // https://godbolt.org/z/ofbGGdx44
1004            if val { self.fetch_or(true, order) } else { self.fetch_and(false, order) }
1005        }
1006        #[cfg(not(any(
1007            target_arch = "riscv32",
1008            target_arch = "riscv64",
1009            target_arch = "loongarch32",
1010            target_arch = "loongarch64",
1011        )))]
1012        {
1013            self.as_atomic_u8().swap(val as u8, order) != 0
1014        }
1015    }
1016
1017    /// Stores a value into the [`bool`] if the current value is the same as the `current` value.
1018    ///
1019    /// The return value is a result indicating whether the new value was written and containing
1020    /// the previous value. On success this value is guaranteed to be equal to `current`.
1021    ///
1022    /// `compare_exchange` takes two [`Ordering`] arguments to describe the memory
1023    /// ordering of this operation. `success` describes the required ordering for the
1024    /// read-modify-write operation that takes place if the comparison with `current` succeeds.
1025    /// `failure` describes the required ordering for the load operation that takes place when
1026    /// the comparison fails. Using [`Acquire`] as success ordering makes the store part
1027    /// of this operation [`Relaxed`], and using [`Release`] makes the successful load
1028    /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
1029    ///
1030    /// # Panics
1031    ///
1032    /// Panics if `failure` is [`Release`], [`AcqRel`].
1033    ///
1034    /// # Examples
1035    ///
1036    /// ```
1037    /// use portable_atomic::{AtomicBool, Ordering};
1038    ///
1039    /// let some_bool = AtomicBool::new(true);
1040    ///
1041    /// assert_eq!(
1042    ///     some_bool.compare_exchange(true, false, Ordering::Acquire, Ordering::Relaxed),
1043    ///     Ok(true)
1044    /// );
1045    /// assert_eq!(some_bool.load(Ordering::Relaxed), false);
1046    ///
1047    /// assert_eq!(
1048    ///     some_bool.compare_exchange(true, true, Ordering::SeqCst, Ordering::Acquire),
1049    ///     Err(false)
1050    /// );
1051    /// assert_eq!(some_bool.load(Ordering::Relaxed), false);
1052    /// ```
1053    #[cfg_attr(docsrs, doc(alias = "compare_and_swap"))]
1054    #[inline]
1055    #[cfg_attr(
1056        any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri),
1057        track_caller
1058    )]
1059    pub fn compare_exchange(
1060        &self,
1061        current: bool,
1062        new: bool,
1063        success: Ordering,
1064        failure: Ordering,
1065    ) -> Result<bool, bool> {
1066        #[cfg(any(
1067            target_arch = "riscv32",
1068            target_arch = "riscv64",
1069            target_arch = "loongarch32",
1070            target_arch = "loongarch64",
1071        ))]
1072        {
1073            // See https://github.com/rust-lang/rust/pull/114034 for details.
1074            // https://github.com/rust-lang/rust/blob/1.84.0/library/core/src/sync/atomic.rs#L249
1075            // https://godbolt.org/z/ofbGGdx44
1076            crate::utils::assert_compare_exchange_ordering(success, failure);
1077            let order = crate::utils::upgrade_success_ordering(success, failure);
1078            let old = if current == new {
1079                // This is a no-op, but we still need to perform the operation
1080                // for memory ordering reasons.
1081                self.fetch_or(false, order)
1082            } else {
1083                // This sets the value to the new one and returns the old one.
1084                self.swap(new, order)
1085            };
1086            if old == current { Ok(old) } else { Err(old) }
1087        }
1088        #[cfg(not(any(
1089            target_arch = "riscv32",
1090            target_arch = "riscv64",
1091            target_arch = "loongarch32",
1092            target_arch = "loongarch64",
1093        )))]
1094        {
1095            match self.as_atomic_u8().compare_exchange(current as u8, new as u8, success, failure) {
1096                Ok(x) => Ok(x != 0),
1097                Err(x) => Err(x != 0),
1098            }
1099        }
1100    }
1101
1102    /// Stores a value into the [`bool`] if the current value is the same as the `current` value.
1103    ///
1104    /// Unlike [`AtomicBool::compare_exchange`], this function is allowed to spuriously fail even when the
1105    /// comparison succeeds, which can result in more efficient code on some platforms. The
1106    /// return value is a result indicating whether the new value was written and containing the
1107    /// previous value.
1108    ///
1109    /// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory
1110    /// ordering of this operation. `success` describes the required ordering for the
1111    /// read-modify-write operation that takes place if the comparison with `current` succeeds.
1112    /// `failure` describes the required ordering for the load operation that takes place when
1113    /// the comparison fails. Using [`Acquire`] as success ordering makes the store part
1114    /// of this operation [`Relaxed`], and using [`Release`] makes the successful load
1115    /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
1116    ///
1117    /// # Panics
1118    ///
1119    /// Panics if `failure` is [`Release`], [`AcqRel`].
1120    ///
1121    /// # Examples
1122    ///
1123    /// ```
1124    /// use portable_atomic::{AtomicBool, Ordering};
1125    ///
1126    /// let val = AtomicBool::new(false);
1127    ///
1128    /// let new = true;
1129    /// let mut old = val.load(Ordering::Relaxed);
1130    /// loop {
1131    ///     match val.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) {
1132    ///         Ok(_) => break,
1133    ///         Err(x) => old = x,
1134    ///     }
1135    /// }
1136    /// ```
1137    #[cfg_attr(docsrs, doc(alias = "compare_and_swap"))]
1138    #[inline]
1139    #[cfg_attr(
1140        any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri),
1141        track_caller
1142    )]
1143    pub fn compare_exchange_weak(
1144        &self,
1145        current: bool,
1146        new: bool,
1147        success: Ordering,
1148        failure: Ordering,
1149    ) -> Result<bool, bool> {
1150        #[cfg(any(
1151            target_arch = "riscv32",
1152            target_arch = "riscv64",
1153            target_arch = "loongarch32",
1154            target_arch = "loongarch64",
1155        ))]
1156        {
1157            // See https://github.com/rust-lang/rust/pull/114034 for details.
1158            // https://github.com/rust-lang/rust/blob/1.84.0/library/core/src/sync/atomic.rs#L249
1159            // https://godbolt.org/z/ofbGGdx44
1160            self.compare_exchange(current, new, success, failure)
1161        }
1162        #[cfg(not(any(
1163            target_arch = "riscv32",
1164            target_arch = "riscv64",
1165            target_arch = "loongarch32",
1166            target_arch = "loongarch64",
1167        )))]
1168        {
1169            match self
1170                .as_atomic_u8()
1171                .compare_exchange_weak(current as u8, new as u8, success, failure)
1172            {
1173                Ok(x) => Ok(x != 0),
1174                Err(x) => Err(x != 0),
1175            }
1176        }
1177    }
1178
1179    /// Logical "and" with a boolean value.
1180    ///
1181    /// Performs a logical "and" operation on the current value and the argument `val`, and sets
1182    /// the new value to the result.
1183    ///
1184    /// Returns the previous value.
1185    ///
1186    /// `fetch_and` takes an [`Ordering`] argument which describes the memory ordering
1187    /// of this operation. All ordering modes are possible. Note that using
1188    /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
1189    /// using [`Release`] makes the load part [`Relaxed`].
1190    ///
1191    /// # Examples
1192    ///
1193    /// ```
1194    /// use portable_atomic::{AtomicBool, Ordering};
1195    ///
1196    /// let foo = AtomicBool::new(true);
1197    /// assert_eq!(foo.fetch_and(false, Ordering::SeqCst), true);
1198    /// assert_eq!(foo.load(Ordering::SeqCst), false);
1199    ///
1200    /// let foo = AtomicBool::new(true);
1201    /// assert_eq!(foo.fetch_and(true, Ordering::SeqCst), true);
1202    /// assert_eq!(foo.load(Ordering::SeqCst), true);
1203    ///
1204    /// let foo = AtomicBool::new(false);
1205    /// assert_eq!(foo.fetch_and(false, Ordering::SeqCst), false);
1206    /// assert_eq!(foo.load(Ordering::SeqCst), false);
1207    /// ```
1208    #[inline]
1209    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
1210    pub fn fetch_and(&self, val: bool, order: Ordering) -> bool {
1211        self.as_atomic_u8().fetch_and(val as u8, order) != 0
1212    }
1213
1214    /// Logical "and" with a boolean value.
1215    ///
1216    /// Performs a logical "and" operation on the current value and the argument `val`, and sets
1217    /// the new value to the result.
1218    ///
1219    /// Unlike `fetch_and`, this does not return the previous value.
1220    ///
1221    /// `and` takes an [`Ordering`] argument which describes the memory ordering
1222    /// of this operation. All ordering modes are possible. Note that using
1223    /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
1224    /// using [`Release`] makes the load part [`Relaxed`].
1225    ///
1226    /// This function may generate more efficient code than `fetch_and` on some platforms.
1227    ///
1228    /// - x86/x86_64: `lock and` instead of `cmpxchg` loop
1229    /// - MSP430: `and` instead of disabling interrupts
1230    ///
1231    /// Note: On x86/x86_64, the use of either function should not usually
1232    /// affect the generated code, because LLVM can properly optimize the case
1233    /// where the result is unused.
1234    ///
1235    /// # Examples
1236    ///
1237    /// ```
1238    /// use portable_atomic::{AtomicBool, Ordering};
1239    ///
1240    /// let foo = AtomicBool::new(true);
1241    /// foo.and(false, Ordering::SeqCst);
1242    /// assert_eq!(foo.load(Ordering::SeqCst), false);
1243    ///
1244    /// let foo = AtomicBool::new(true);
1245    /// foo.and(true, Ordering::SeqCst);
1246    /// assert_eq!(foo.load(Ordering::SeqCst), true);
1247    ///
1248    /// let foo = AtomicBool::new(false);
1249    /// foo.and(false, Ordering::SeqCst);
1250    /// assert_eq!(foo.load(Ordering::SeqCst), false);
1251    /// ```
1252    #[inline]
1253    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
1254    pub fn and(&self, val: bool, order: Ordering) {
1255        self.as_atomic_u8().and(val as u8, order);
1256    }
1257
1258    /// Logical "nand" with a boolean value.
1259    ///
1260    /// Performs a logical "nand" operation on the current value and the argument `val`, and sets
1261    /// the new value to the result.
1262    ///
1263    /// Returns the previous value.
1264    ///
1265    /// `fetch_nand` takes an [`Ordering`] argument which describes the memory ordering
1266    /// of this operation. All ordering modes are possible. Note that using
1267    /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
1268    /// using [`Release`] makes the load part [`Relaxed`].
1269    ///
1270    /// # Examples
1271    ///
1272    /// ```
1273    /// use portable_atomic::{AtomicBool, Ordering};
1274    ///
1275    /// let foo = AtomicBool::new(true);
1276    /// assert_eq!(foo.fetch_nand(false, Ordering::SeqCst), true);
1277    /// assert_eq!(foo.load(Ordering::SeqCst), true);
1278    ///
1279    /// let foo = AtomicBool::new(true);
1280    /// assert_eq!(foo.fetch_nand(true, Ordering::SeqCst), true);
1281    /// assert_eq!(foo.load(Ordering::SeqCst) as usize, 0);
1282    /// assert_eq!(foo.load(Ordering::SeqCst), false);
1283    ///
1284    /// let foo = AtomicBool::new(false);
1285    /// assert_eq!(foo.fetch_nand(false, Ordering::SeqCst), false);
1286    /// assert_eq!(foo.load(Ordering::SeqCst), true);
1287    /// ```
1288    #[inline]
1289    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
1290    pub fn fetch_nand(&self, val: bool, order: Ordering) -> bool {
1291        // https://github.com/rust-lang/rust/blob/1.84.0/library/core/src/sync/atomic.rs#L973-L985
1292        if val {
1293            // !(x & true) == !x
1294            // We must invert the bool.
1295            self.fetch_xor(true, order)
1296        } else {
1297            // !(x & false) == true
1298            // We must set the bool to true.
1299            self.swap(true, order)
1300        }
1301    }
1302
1303    /// Logical "or" with a boolean value.
1304    ///
1305    /// Performs a logical "or" operation on the current value and the argument `val`, and sets the
1306    /// new value to the result.
1307    ///
1308    /// Returns the previous value.
1309    ///
1310    /// `fetch_or` takes an [`Ordering`] argument which describes the memory ordering
1311    /// of this operation. All ordering modes are possible. Note that using
1312    /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
1313    /// using [`Release`] makes the load part [`Relaxed`].
1314    ///
1315    /// # Examples
1316    ///
1317    /// ```
1318    /// use portable_atomic::{AtomicBool, Ordering};
1319    ///
1320    /// let foo = AtomicBool::new(true);
1321    /// assert_eq!(foo.fetch_or(false, Ordering::SeqCst), true);
1322    /// assert_eq!(foo.load(Ordering::SeqCst), true);
1323    ///
1324    /// let foo = AtomicBool::new(true);
1325    /// assert_eq!(foo.fetch_or(true, Ordering::SeqCst), true);
1326    /// assert_eq!(foo.load(Ordering::SeqCst), true);
1327    ///
1328    /// let foo = AtomicBool::new(false);
1329    /// assert_eq!(foo.fetch_or(false, Ordering::SeqCst), false);
1330    /// assert_eq!(foo.load(Ordering::SeqCst), false);
1331    /// ```
1332    #[inline]
1333    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
1334    pub fn fetch_or(&self, val: bool, order: Ordering) -> bool {
1335        self.as_atomic_u8().fetch_or(val as u8, order) != 0
1336    }
1337
1338    /// Logical "or" with a boolean value.
1339    ///
1340    /// Performs a logical "or" operation on the current value and the argument `val`, and sets the
1341    /// new value to the result.
1342    ///
1343    /// Unlike `fetch_or`, this does not return the previous value.
1344    ///
1345    /// `or` takes an [`Ordering`] argument which describes the memory ordering
1346    /// of this operation. All ordering modes are possible. Note that using
1347    /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
1348    /// using [`Release`] makes the load part [`Relaxed`].
1349    ///
1350    /// This function may generate more efficient code than `fetch_or` on some platforms.
1351    ///
1352    /// - x86/x86_64: `lock or` instead of `cmpxchg` loop
1353    /// - MSP430: `bis` instead of disabling interrupts
1354    ///
1355    /// Note: On x86/x86_64, the use of either function should not usually
1356    /// affect the generated code, because LLVM can properly optimize the case
1357    /// where the result is unused.
1358    ///
1359    /// # Examples
1360    ///
1361    /// ```
1362    /// use portable_atomic::{AtomicBool, Ordering};
1363    ///
1364    /// let foo = AtomicBool::new(true);
1365    /// foo.or(false, Ordering::SeqCst);
1366    /// assert_eq!(foo.load(Ordering::SeqCst), true);
1367    ///
1368    /// let foo = AtomicBool::new(true);
1369    /// foo.or(true, Ordering::SeqCst);
1370    /// assert_eq!(foo.load(Ordering::SeqCst), true);
1371    ///
1372    /// let foo = AtomicBool::new(false);
1373    /// foo.or(false, Ordering::SeqCst);
1374    /// assert_eq!(foo.load(Ordering::SeqCst), false);
1375    /// ```
1376    #[inline]
1377    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
1378    pub fn or(&self, val: bool, order: Ordering) {
1379        self.as_atomic_u8().or(val as u8, order);
1380    }
1381
1382    /// Logical "xor" with a boolean value.
1383    ///
1384    /// Performs a logical "xor" operation on the current value and the argument `val`, and sets
1385    /// the new value to the result.
1386    ///
1387    /// Returns the previous value.
1388    ///
1389    /// `fetch_xor` takes an [`Ordering`] argument which describes the memory ordering
1390    /// of this operation. All ordering modes are possible. Note that using
1391    /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
1392    /// using [`Release`] makes the load part [`Relaxed`].
1393    ///
1394    /// # Examples
1395    ///
1396    /// ```
1397    /// use portable_atomic::{AtomicBool, Ordering};
1398    ///
1399    /// let foo = AtomicBool::new(true);
1400    /// assert_eq!(foo.fetch_xor(false, Ordering::SeqCst), true);
1401    /// assert_eq!(foo.load(Ordering::SeqCst), true);
1402    ///
1403    /// let foo = AtomicBool::new(true);
1404    /// assert_eq!(foo.fetch_xor(true, Ordering::SeqCst), true);
1405    /// assert_eq!(foo.load(Ordering::SeqCst), false);
1406    ///
1407    /// let foo = AtomicBool::new(false);
1408    /// assert_eq!(foo.fetch_xor(false, Ordering::SeqCst), false);
1409    /// assert_eq!(foo.load(Ordering::SeqCst), false);
1410    /// ```
1411    #[inline]
1412    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
1413    pub fn fetch_xor(&self, val: bool, order: Ordering) -> bool {
1414        self.as_atomic_u8().fetch_xor(val as u8, order) != 0
1415    }
1416
1417    /// Logical "xor" with a boolean value.
1418    ///
1419    /// Performs a logical "xor" operation on the current value and the argument `val`, and sets
1420    /// the new value to the result.
1421    ///
1422    /// Unlike `fetch_xor`, this does not return the previous value.
1423    ///
1424    /// `xor` takes an [`Ordering`] argument which describes the memory ordering
1425    /// of this operation. All ordering modes are possible. Note that using
1426    /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
1427    /// using [`Release`] makes the load part [`Relaxed`].
1428    ///
1429    /// This function may generate more efficient code than `fetch_xor` on some platforms.
1430    ///
1431    /// - x86/x86_64: `lock xor` instead of `cmpxchg` loop
1432    /// - MSP430: `xor` instead of disabling interrupts
1433    ///
1434    /// Note: On x86/x86_64, the use of either function should not usually
1435    /// affect the generated code, because LLVM can properly optimize the case
1436    /// where the result is unused.
1437    ///
1438    /// # Examples
1439    ///
1440    /// ```
1441    /// use portable_atomic::{AtomicBool, Ordering};
1442    ///
1443    /// let foo = AtomicBool::new(true);
1444    /// foo.xor(false, Ordering::SeqCst);
1445    /// assert_eq!(foo.load(Ordering::SeqCst), true);
1446    ///
1447    /// let foo = AtomicBool::new(true);
1448    /// foo.xor(true, Ordering::SeqCst);
1449    /// assert_eq!(foo.load(Ordering::SeqCst), false);
1450    ///
1451    /// let foo = AtomicBool::new(false);
1452    /// foo.xor(false, Ordering::SeqCst);
1453    /// assert_eq!(foo.load(Ordering::SeqCst), false);
1454    /// ```
1455    #[inline]
1456    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
1457    pub fn xor(&self, val: bool, order: Ordering) {
1458        self.as_atomic_u8().xor(val as u8, order);
1459    }
1460
1461    /// Logical "not" with a boolean value.
1462    ///
1463    /// Performs a logical "not" operation on the current value, and sets
1464    /// the new value to the result.
1465    ///
1466    /// Returns the previous value.
1467    ///
1468    /// `fetch_not` takes an [`Ordering`] argument which describes the memory ordering
1469    /// of this operation. All ordering modes are possible. Note that using
1470    /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
1471    /// using [`Release`] makes the load part [`Relaxed`].
1472    ///
1473    /// # Examples
1474    ///
1475    /// ```
1476    /// use portable_atomic::{AtomicBool, Ordering};
1477    ///
1478    /// let foo = AtomicBool::new(true);
1479    /// assert_eq!(foo.fetch_not(Ordering::SeqCst), true);
1480    /// assert_eq!(foo.load(Ordering::SeqCst), false);
1481    ///
1482    /// let foo = AtomicBool::new(false);
1483    /// assert_eq!(foo.fetch_not(Ordering::SeqCst), false);
1484    /// assert_eq!(foo.load(Ordering::SeqCst), true);
1485    /// ```
1486    #[inline]
1487    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
1488    pub fn fetch_not(&self, order: Ordering) -> bool {
1489        self.fetch_xor(true, order)
1490    }
1491
1492    /// Logical "not" with a boolean value.
1493    ///
1494    /// Performs a logical "not" operation on the current value, and sets
1495    /// the new value to the result.
1496    ///
1497    /// Unlike `fetch_not`, this does not return the previous value.
1498    ///
1499    /// `not` takes an [`Ordering`] argument which describes the memory ordering
1500    /// of this operation. All ordering modes are possible. Note that using
1501    /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
1502    /// using [`Release`] makes the load part [`Relaxed`].
1503    ///
1504    /// This function may generate more efficient code than `fetch_not` on some platforms.
1505    ///
1506    /// - x86/x86_64: `lock xor` instead of `cmpxchg` loop
1507    /// - MSP430: `xor` instead of disabling interrupts
1508    ///
1509    /// Note: On x86/x86_64, the use of either function should not usually
1510    /// affect the generated code, because LLVM can properly optimize the case
1511    /// where the result is unused.
1512    ///
1513    /// # Examples
1514    ///
1515    /// ```
1516    /// use portable_atomic::{AtomicBool, Ordering};
1517    ///
1518    /// let foo = AtomicBool::new(true);
1519    /// foo.not(Ordering::SeqCst);
1520    /// assert_eq!(foo.load(Ordering::SeqCst), false);
1521    ///
1522    /// let foo = AtomicBool::new(false);
1523    /// foo.not(Ordering::SeqCst);
1524    /// assert_eq!(foo.load(Ordering::SeqCst), true);
1525    /// ```
1526    #[inline]
1527    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
1528    pub fn not(&self, order: Ordering) {
1529        self.xor(true, order);
1530    }
1531
1532    /// Fetches the value, and applies a function to it that returns an optional
1533    /// new value. Returns a `Result` of `Ok(previous_value)` if the function
1534    /// returned `Some(_)`, else `Err(previous_value)`.
1535    ///
1536    /// Note: This may call the function multiple times if the value has been
1537    /// changed from other threads in the meantime, as long as the function
1538    /// returns `Some(_)`, but the function will have been applied only once to
1539    /// the stored value.
1540    ///
1541    /// `fetch_update` takes two [`Ordering`] arguments to describe the memory
1542    /// ordering of this operation. The first describes the required ordering for
1543    /// when the operation finally succeeds while the second describes the
1544    /// required ordering for loads. These correspond to the success and failure
1545    /// orderings of [`compare_exchange`](Self::compare_exchange) respectively.
1546    ///
1547    /// Using [`Acquire`] as success ordering makes the store part of this
1548    /// operation [`Relaxed`], and using [`Release`] makes the final successful
1549    /// load [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`],
1550    /// [`Acquire`] or [`Relaxed`].
1551    ///
1552    /// # Considerations
1553    ///
1554    /// This method is not magic; it is not provided by the hardware.
1555    /// It is implemented in terms of [`compare_exchange_weak`](Self::compare_exchange_weak),
1556    /// and suffers from the same drawbacks.
1557    /// In particular, this method will not circumvent the [ABA Problem].
1558    ///
1559    /// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
1560    ///
1561    /// # Panics
1562    ///
1563    /// Panics if `fetch_order` is [`Release`], [`AcqRel`].
1564    ///
1565    /// # Examples
1566    ///
1567    /// ```
1568    /// use portable_atomic::{AtomicBool, Ordering};
1569    ///
1570    /// let x = AtomicBool::new(false);
1571    /// assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |_| None), Err(false));
1572    /// assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(!x)), Ok(false));
1573    /// assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(!x)), Ok(true));
1574    /// assert_eq!(x.load(Ordering::SeqCst), false);
1575    /// ```
1576    #[inline]
1577    #[cfg_attr(
1578        any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri),
1579        track_caller
1580    )]
1581    pub fn fetch_update<F>(
1582        &self,
1583        set_order: Ordering,
1584        fetch_order: Ordering,
1585        mut f: F,
1586    ) -> Result<bool, bool>
1587    where
1588        F: FnMut(bool) -> Option<bool>,
1589    {
1590        let mut prev = self.load(fetch_order);
1591        while let Some(next) = f(prev) {
1592            match self.compare_exchange_weak(prev, next, set_order, fetch_order) {
1593                x @ Ok(_) => return x,
1594                Err(next_prev) => prev = next_prev,
1595            }
1596        }
1597        Err(prev)
1598    }
1599    } // cfg_has_atomic_cas_or_amo32!
1600
1601    const_fn! {
1602        // This function is actually `const fn`-compatible on Rust 1.32+,
1603        // but makes `const fn` only on Rust 1.58+ to match other atomic types.
1604        const_if: #[cfg(not(portable_atomic_no_const_raw_ptr_deref))];
1605        /// Returns a mutable pointer to the underlying [`bool`].
1606        ///
1607        /// Returning an `*mut` pointer from a shared reference to this atomic is
1608        /// safe because the atomic types work with interior mutability. Any use of
1609        /// the returned raw pointer requires an `unsafe` block and has to uphold
1610        /// the safety requirements. If there is concurrent access, note the following
1611        /// additional safety requirements:
1612        ///
1613        /// - If this atomic type is [lock-free](Self::is_lock_free), any concurrent
1614        ///   operations on it must be atomic.
1615        /// - Otherwise, any concurrent operations on it must be compatible with
1616        ///   operations performed by this atomic type.
1617        ///
1618        /// This is `const fn` on Rust 1.58+.
1619        #[inline]
1620        pub const fn as_ptr(&self) -> *mut bool {
1621            self.v.get() as *mut bool
1622        }
1623    }
1624
1625    #[inline(always)]
1626    fn as_atomic_u8(&self) -> &imp::AtomicU8 {
1627        // SAFETY: AtomicBool and imp::AtomicU8 have the same layout,
1628        // and both access data in the same way.
1629        unsafe { &*(self as *const Self as *const imp::AtomicU8) }
1630    }
1631}
1632// See https://github.com/taiki-e/portable-atomic/issues/180
1633#[cfg(not(feature = "require-cas"))]
1634cfg_no_atomic_cas! {
1635#[doc(hidden)]
1636#[allow(unused_variables, clippy::unused_self, clippy::extra_unused_lifetimes)]
1637impl<'a> AtomicBool {
1638    cfg_no_atomic_cas_or_amo32! {
1639    #[inline]
1640    pub fn swap(&self, val: bool, order: Ordering) -> bool
1641    where
1642        &'a Self: HasSwap,
1643    {
1644        unimplemented!()
1645    }
1646    #[inline]
1647    pub fn compare_exchange(
1648        &self,
1649        current: bool,
1650        new: bool,
1651        success: Ordering,
1652        failure: Ordering,
1653    ) -> Result<bool, bool>
1654    where
1655        &'a Self: HasCompareExchange,
1656    {
1657        unimplemented!()
1658    }
1659    #[inline]
1660    pub fn compare_exchange_weak(
1661        &self,
1662        current: bool,
1663        new: bool,
1664        success: Ordering,
1665        failure: Ordering,
1666    ) -> Result<bool, bool>
1667    where
1668        &'a Self: HasCompareExchangeWeak,
1669    {
1670        unimplemented!()
1671    }
1672    #[inline]
1673    pub fn fetch_and(&self, val: bool, order: Ordering) -> bool
1674    where
1675        &'a Self: HasFetchAnd,
1676    {
1677        unimplemented!()
1678    }
1679    #[inline]
1680    pub fn and(&self, val: bool, order: Ordering)
1681    where
1682        &'a Self: HasAnd,
1683    {
1684        unimplemented!()
1685    }
1686    #[inline]
1687    pub fn fetch_nand(&self, val: bool, order: Ordering) -> bool
1688    where
1689        &'a Self: HasFetchNand,
1690    {
1691        unimplemented!()
1692    }
1693    #[inline]
1694    pub fn fetch_or(&self, val: bool, order: Ordering) -> bool
1695    where
1696        &'a Self: HasFetchOr,
1697    {
1698        unimplemented!()
1699    }
1700    #[inline]
1701    pub fn or(&self, val: bool, order: Ordering)
1702    where
1703        &'a Self: HasOr,
1704    {
1705        unimplemented!()
1706    }
1707    #[inline]
1708    pub fn fetch_xor(&self, val: bool, order: Ordering) -> bool
1709    where
1710        &'a Self: HasFetchXor,
1711    {
1712        unimplemented!()
1713    }
1714    #[inline]
1715    pub fn xor(&self, val: bool, order: Ordering)
1716    where
1717        &'a Self: HasXor,
1718    {
1719        unimplemented!()
1720    }
1721    #[inline]
1722    pub fn fetch_not(&self, order: Ordering) -> bool
1723    where
1724        &'a Self: HasFetchNot,
1725    {
1726        unimplemented!()
1727    }
1728    #[inline]
1729    pub fn not(&self, order: Ordering)
1730    where
1731        &'a Self: HasNot,
1732    {
1733        unimplemented!()
1734    }
1735    #[inline]
1736    pub fn fetch_update<F>(
1737        &self,
1738        set_order: Ordering,
1739        fetch_order: Ordering,
1740        f: F,
1741    ) -> Result<bool, bool>
1742    where
1743        F: FnMut(bool) -> Option<bool>,
1744        &'a Self: HasFetchUpdate,
1745    {
1746        unimplemented!()
1747    }
1748    } // cfg_no_atomic_cas_or_amo32!
1749}
1750} // cfg_no_atomic_cas!
1751} // cfg_has_atomic_8!
1752
1753cfg_has_atomic_ptr! {
1754/// A raw pointer type which can be safely shared between threads.
1755///
1756/// This type has the same in-memory representation as a `*mut T`.
1757///
1758/// If the compiler and the platform support atomic loads and stores of pointers,
1759/// this type is a wrapper for the standard library's
1760/// [`AtomicPtr`](core::sync::atomic::AtomicPtr). If the platform supports it
1761/// but the compiler does not, atomic operations are implemented using inline
1762/// assembly.
1763// We can use #[repr(transparent)] here, but #[repr(C, align(N))]
1764// will show clearer docs.
1765#[cfg_attr(target_pointer_width = "16", repr(C, align(2)))]
1766#[cfg_attr(target_pointer_width = "32", repr(C, align(4)))]
1767#[cfg_attr(target_pointer_width = "64", repr(C, align(8)))]
1768#[cfg_attr(target_pointer_width = "128", repr(C, align(16)))]
1769pub struct AtomicPtr<T> {
1770    inner: imp::AtomicPtr<T>,
1771}
1772
1773impl<T> Default for AtomicPtr<T> {
1774    /// Creates a null `AtomicPtr<T>`.
1775    #[inline]
1776    fn default() -> Self {
1777        Self::new(ptr::null_mut())
1778    }
1779}
1780
1781impl<T> From<*mut T> for AtomicPtr<T> {
1782    #[inline]
1783    fn from(p: *mut T) -> Self {
1784        Self::new(p)
1785    }
1786}
1787
1788impl<T> fmt::Debug for AtomicPtr<T> {
1789    #[inline] // fmt is not hot path, but #[inline] on fmt seems to still be useful: https://github.com/rust-lang/rust/pull/117727
1790    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1791        // std atomic types use Relaxed in Debug::fmt: https://github.com/rust-lang/rust/blob/1.84.0/library/core/src/sync/atomic.rs#L2188
1792        fmt::Debug::fmt(&self.load(Ordering::Relaxed), f)
1793    }
1794}
1795
1796impl<T> fmt::Pointer for AtomicPtr<T> {
1797    #[inline] // fmt is not hot path, but #[inline] on fmt seems to still be useful: https://github.com/rust-lang/rust/pull/117727
1798    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1799        // std atomic types use Relaxed in Debug::fmt: https://github.com/rust-lang/rust/blob/1.84.0/library/core/src/sync/atomic.rs#L2188
1800        fmt::Pointer::fmt(&self.load(Ordering::Relaxed), f)
1801    }
1802}
1803
1804// UnwindSafe is implicitly implemented.
1805#[cfg(not(portable_atomic_no_core_unwind_safe))]
1806impl<T> core::panic::RefUnwindSafe for AtomicPtr<T> {}
1807#[cfg(all(portable_atomic_no_core_unwind_safe, feature = "std"))]
1808impl<T> std::panic::RefUnwindSafe for AtomicPtr<T> {}
1809
1810impl<T> AtomicPtr<T> {
1811    /// Creates a new `AtomicPtr`.
1812    ///
1813    /// # Examples
1814    ///
1815    /// ```
1816    /// use portable_atomic::AtomicPtr;
1817    ///
1818    /// let ptr = &mut 5;
1819    /// let atomic_ptr = AtomicPtr::new(ptr);
1820    /// ```
1821    #[inline]
1822    #[must_use]
1823    pub const fn new(p: *mut T) -> Self {
1824        static_assert_layout!(AtomicPtr<()>, *mut ());
1825        Self { inner: imp::AtomicPtr::new(p) }
1826    }
1827
1828    // TODO: update docs based on https://github.com/rust-lang/rust/pull/116762
1829    const_fn! {
1830        const_if: #[cfg(not(portable_atomic_no_const_raw_ptr_deref))];
1831        /// Creates a new `AtomicPtr` from a pointer.
1832        ///
1833        /// This is `const fn` on Rust 1.58+.
1834        ///
1835        /// # Safety
1836        ///
1837        /// * `ptr` must be aligned to `align_of::<AtomicPtr<T>>()` (note that on some platforms this
1838        ///   can be bigger than `align_of::<*mut T>()`).
1839        /// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`.
1840        /// * If this atomic type is [lock-free](Self::is_lock_free), non-atomic accesses to the value
1841        ///   behind `ptr` must have a happens-before relationship with atomic accesses via the returned
1842        ///   value (or vice-versa).
1843        ///   * In other words, time periods where the value is accessed atomically may not overlap
1844        ///     with periods where the value is accessed non-atomically.
1845        ///   * This requirement is trivially satisfied if `ptr` is never used non-atomically for the
1846        ///     duration of lifetime `'a`. Most use cases should be able to follow this guideline.
1847        ///   * This requirement is also trivially satisfied if all accesses (atomic or not) are done
1848        ///     from the same thread.
1849        /// * If this atomic type is *not* lock-free:
1850        ///   * Any accesses to the value behind `ptr` must have a happens-before relationship
1851        ///     with accesses via the returned value (or vice-versa).
1852        ///   * Any concurrent accesses to the value behind `ptr` for the duration of lifetime `'a` must
1853        ///     be compatible with operations performed by this atomic type.
1854        /// * This method must not be used to create overlapping or mixed-size atomic accesses, as
1855        ///   these are not supported by the memory model.
1856        ///
1857        /// [valid]: core::ptr#safety
1858        #[inline]
1859        #[must_use]
1860        pub const unsafe fn from_ptr<'a>(ptr: *mut *mut T) -> &'a Self {
1861            #[allow(clippy::cast_ptr_alignment)]
1862            // SAFETY: guaranteed by the caller
1863            unsafe { &*(ptr as *mut Self as *const Self) }
1864        }
1865    }
1866
1867    /// Returns `true` if operations on values of this type are lock-free.
1868    ///
1869    /// If the compiler or the platform doesn't support the necessary
1870    /// atomic instructions, global locks for every potentially
1871    /// concurrent atomic operation will be used.
1872    ///
1873    /// This function is guaranteed to always return the same result.
1874    ///
1875    /// # Examples
1876    ///
1877    /// ```
1878    /// use portable_atomic::AtomicPtr;
1879    ///
1880    /// let is_lock_free = AtomicPtr::<()>::is_lock_free();
1881    /// ```
1882    #[inline]
1883    #[must_use]
1884    pub fn is_lock_free() -> bool {
1885        <imp::AtomicPtr<T>>::is_lock_free()
1886    }
1887
1888    /// Returns `true` if operations on values of this type are lock-free.
1889    ///
1890    /// If the compiler or the platform doesn't support the necessary
1891    /// atomic instructions, global locks for every potentially
1892    /// concurrent atomic operation will be used.
1893    ///
1894    /// **Note:** If the atomic operation relies on dynamic CPU feature detection,
1895    /// this type may be lock-free even if the function returns false.
1896    ///
1897    /// # Examples
1898    ///
1899    /// ```
1900    /// use portable_atomic::AtomicPtr;
1901    ///
1902    /// const IS_ALWAYS_LOCK_FREE: bool = AtomicPtr::<()>::is_always_lock_free();
1903    /// ```
1904    #[inline]
1905    #[must_use]
1906    pub const fn is_always_lock_free() -> bool {
1907        <imp::AtomicPtr<T>>::IS_ALWAYS_LOCK_FREE
1908    }
1909    #[cfg(test)]
1910    const IS_ALWAYS_LOCK_FREE: bool = Self::is_always_lock_free();
1911
1912    const_fn! {
1913        const_if: #[cfg(not(portable_atomic_no_const_mut_refs))];
1914        /// Returns a mutable reference to the underlying pointer.
1915        ///
1916        /// This is safe because the mutable reference guarantees that no other threads are
1917        /// concurrently accessing the atomic data.
1918        ///
1919        /// This is `const fn` on Rust 1.83+.
1920        ///
1921        /// # Examples
1922        ///
1923        /// ```
1924        /// use portable_atomic::{AtomicPtr, Ordering};
1925        ///
1926        /// let mut data = 10;
1927        /// let mut atomic_ptr = AtomicPtr::new(&mut data);
1928        /// let mut other_data = 5;
1929        /// *atomic_ptr.get_mut() = &mut other_data;
1930        /// assert_eq!(unsafe { *atomic_ptr.load(Ordering::SeqCst) }, 5);
1931        /// ```
1932        #[inline]
1933        pub const fn get_mut(&mut self) -> &mut *mut T {
1934            // SAFETY: the mutable reference guarantees unique ownership.
1935            // (core::sync::atomic::Atomic*::get_mut is not const yet)
1936            unsafe { &mut *self.as_ptr() }
1937        }
1938    }
1939
1940    // TODO: Add from_mut/get_mut_slice/from_mut_slice once it is stable on std atomic types.
1941    // https://github.com/rust-lang/rust/issues/76314
1942
1943    const_fn! {
1944        const_if: #[cfg(not(portable_atomic_no_const_transmute))];
1945        /// Consumes the atomic and returns the contained value.
1946        ///
1947        /// This is safe because passing `self` by value guarantees that no other threads are
1948        /// concurrently accessing the atomic data.
1949        ///
1950        /// This is `const fn` on Rust 1.56+.
1951        ///
1952        /// # Examples
1953        ///
1954        /// ```
1955        /// use portable_atomic::AtomicPtr;
1956        ///
1957        /// let mut data = 5;
1958        /// let atomic_ptr = AtomicPtr::new(&mut data);
1959        /// assert_eq!(unsafe { *atomic_ptr.into_inner() }, 5);
1960        /// ```
1961        #[inline]
1962        pub const fn into_inner(self) -> *mut T {
1963            // SAFETY: AtomicPtr<T> and *mut T have the same size and in-memory representations,
1964            // so they can be safely transmuted.
1965            // (const UnsafeCell::into_inner is unstable)
1966            unsafe { core::mem::transmute(self) }
1967        }
1968    }
1969
1970    /// Loads a value from the pointer.
1971    ///
1972    /// `load` takes an [`Ordering`] argument which describes the memory ordering
1973    /// of this operation. Possible values are [`SeqCst`], [`Acquire`] and [`Relaxed`].
1974    ///
1975    /// # Panics
1976    ///
1977    /// Panics if `order` is [`Release`] or [`AcqRel`].
1978    ///
1979    /// # Examples
1980    ///
1981    /// ```
1982    /// use portable_atomic::{AtomicPtr, Ordering};
1983    ///
1984    /// let ptr = &mut 5;
1985    /// let some_ptr = AtomicPtr::new(ptr);
1986    ///
1987    /// let value = some_ptr.load(Ordering::Relaxed);
1988    /// ```
1989    #[inline]
1990    #[cfg_attr(
1991        any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri),
1992        track_caller
1993    )]
1994    pub fn load(&self, order: Ordering) -> *mut T {
1995        self.inner.load(order)
1996    }
1997
1998    /// Stores a value into the pointer.
1999    ///
2000    /// `store` takes an [`Ordering`] argument which describes the memory ordering
2001    /// of this operation. Possible values are [`SeqCst`], [`Release`] and [`Relaxed`].
2002    ///
2003    /// # Panics
2004    ///
2005    /// Panics if `order` is [`Acquire`] or [`AcqRel`].
2006    ///
2007    /// # Examples
2008    ///
2009    /// ```
2010    /// use portable_atomic::{AtomicPtr, Ordering};
2011    ///
2012    /// let ptr = &mut 5;
2013    /// let some_ptr = AtomicPtr::new(ptr);
2014    ///
2015    /// let other_ptr = &mut 10;
2016    ///
2017    /// some_ptr.store(other_ptr, Ordering::Relaxed);
2018    /// ```
2019    #[inline]
2020    #[cfg_attr(
2021        any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri),
2022        track_caller
2023    )]
2024    pub fn store(&self, ptr: *mut T, order: Ordering) {
2025        self.inner.store(ptr, order);
2026    }
2027
2028    cfg_has_atomic_cas_or_amo32! {
2029    /// Stores a value into the pointer, returning the previous value.
2030    ///
2031    /// `swap` takes an [`Ordering`] argument which describes the memory ordering
2032    /// of this operation. All ordering modes are possible. Note that using
2033    /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
2034    /// using [`Release`] makes the load part [`Relaxed`].
2035    ///
2036    /// # Examples
2037    ///
2038    /// ```
2039    /// use portable_atomic::{AtomicPtr, Ordering};
2040    ///
2041    /// let ptr = &mut 5;
2042    /// let some_ptr = AtomicPtr::new(ptr);
2043    ///
2044    /// let other_ptr = &mut 10;
2045    ///
2046    /// let value = some_ptr.swap(other_ptr, Ordering::Relaxed);
2047    /// ```
2048    #[inline]
2049    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
2050    pub fn swap(&self, ptr: *mut T, order: Ordering) -> *mut T {
2051        self.inner.swap(ptr, order)
2052    }
2053
2054    cfg_has_atomic_cas! {
2055    /// Stores a value into the pointer if the current value is the same as the `current` value.
2056    ///
2057    /// The return value is a result indicating whether the new value was written and containing
2058    /// the previous value. On success this value is guaranteed to be equal to `current`.
2059    ///
2060    /// `compare_exchange` takes two [`Ordering`] arguments to describe the memory
2061    /// ordering of this operation. `success` describes the required ordering for the
2062    /// read-modify-write operation that takes place if the comparison with `current` succeeds.
2063    /// `failure` describes the required ordering for the load operation that takes place when
2064    /// the comparison fails. Using [`Acquire`] as success ordering makes the store part
2065    /// of this operation [`Relaxed`], and using [`Release`] makes the successful load
2066    /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
2067    ///
2068    /// # Panics
2069    ///
2070    /// Panics if `failure` is [`Release`], [`AcqRel`].
2071    ///
2072    /// # Examples
2073    ///
2074    /// ```
2075    /// use portable_atomic::{AtomicPtr, Ordering};
2076    ///
2077    /// let ptr = &mut 5;
2078    /// let some_ptr = AtomicPtr::new(ptr);
2079    ///
2080    /// let other_ptr = &mut 10;
2081    ///
2082    /// let value = some_ptr.compare_exchange(ptr, other_ptr, Ordering::SeqCst, Ordering::Relaxed);
2083    /// ```
2084    #[cfg_attr(docsrs, doc(alias = "compare_and_swap"))]
2085    #[inline]
2086    #[cfg_attr(
2087        any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri),
2088        track_caller
2089    )]
2090    pub fn compare_exchange(
2091        &self,
2092        current: *mut T,
2093        new: *mut T,
2094        success: Ordering,
2095        failure: Ordering,
2096    ) -> Result<*mut T, *mut T> {
2097        self.inner.compare_exchange(current, new, success, failure)
2098    }
2099
2100    /// Stores a value into the pointer if the current value is the same as the `current` value.
2101    ///
2102    /// Unlike [`AtomicPtr::compare_exchange`], this function is allowed to spuriously fail even when the
2103    /// comparison succeeds, which can result in more efficient code on some platforms. The
2104    /// return value is a result indicating whether the new value was written and containing the
2105    /// previous value.
2106    ///
2107    /// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory
2108    /// ordering of this operation. `success` describes the required ordering for the
2109    /// read-modify-write operation that takes place if the comparison with `current` succeeds.
2110    /// `failure` describes the required ordering for the load operation that takes place when
2111    /// the comparison fails. Using [`Acquire`] as success ordering makes the store part
2112    /// of this operation [`Relaxed`], and using [`Release`] makes the successful load
2113    /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
2114    ///
2115    /// # Panics
2116    ///
2117    /// Panics if `failure` is [`Release`], [`AcqRel`].
2118    ///
2119    /// # Examples
2120    ///
2121    /// ```
2122    /// use portable_atomic::{AtomicPtr, Ordering};
2123    ///
2124    /// let some_ptr = AtomicPtr::new(&mut 5);
2125    ///
2126    /// let new = &mut 10;
2127    /// let mut old = some_ptr.load(Ordering::Relaxed);
2128    /// loop {
2129    ///     match some_ptr.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) {
2130    ///         Ok(_) => break,
2131    ///         Err(x) => old = x,
2132    ///     }
2133    /// }
2134    /// ```
2135    #[cfg_attr(docsrs, doc(alias = "compare_and_swap"))]
2136    #[inline]
2137    #[cfg_attr(
2138        any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri),
2139        track_caller
2140    )]
2141    pub fn compare_exchange_weak(
2142        &self,
2143        current: *mut T,
2144        new: *mut T,
2145        success: Ordering,
2146        failure: Ordering,
2147    ) -> Result<*mut T, *mut T> {
2148        self.inner.compare_exchange_weak(current, new, success, failure)
2149    }
2150
2151    /// Fetches the value, and applies a function to it that returns an optional
2152    /// new value. Returns a `Result` of `Ok(previous_value)` if the function
2153    /// returned `Some(_)`, else `Err(previous_value)`.
2154    ///
2155    /// Note: This may call the function multiple times if the value has been
2156    /// changed from other threads in the meantime, as long as the function
2157    /// returns `Some(_)`, but the function will have been applied only once to
2158    /// the stored value.
2159    ///
2160    /// `fetch_update` takes two [`Ordering`] arguments to describe the memory
2161    /// ordering of this operation. The first describes the required ordering for
2162    /// when the operation finally succeeds while the second describes the
2163    /// required ordering for loads. These correspond to the success and failure
2164    /// orderings of [`compare_exchange`](Self::compare_exchange) respectively.
2165    ///
2166    /// Using [`Acquire`] as success ordering makes the store part of this
2167    /// operation [`Relaxed`], and using [`Release`] makes the final successful
2168    /// load [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`],
2169    /// [`Acquire`] or [`Relaxed`].
2170    ///
2171    /// # Panics
2172    ///
2173    /// Panics if `fetch_order` is [`Release`], [`AcqRel`].
2174    ///
2175    /// # Considerations
2176    ///
2177    /// This method is not magic; it is not provided by the hardware.
2178    /// It is implemented in terms of [`compare_exchange_weak`](Self::compare_exchange_weak),
2179    /// and suffers from the same drawbacks.
2180    /// In particular, this method will not circumvent the [ABA Problem].
2181    ///
2182    /// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
2183    ///
2184    /// # Examples
2185    ///
2186    /// ```
2187    /// use portable_atomic::{AtomicPtr, Ordering};
2188    ///
2189    /// let ptr: *mut _ = &mut 5;
2190    /// let some_ptr = AtomicPtr::new(ptr);
2191    ///
2192    /// let new: *mut _ = &mut 10;
2193    /// assert_eq!(some_ptr.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |_| None), Err(ptr));
2194    /// let result = some_ptr.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| {
2195    ///     if x == ptr {
2196    ///         Some(new)
2197    ///     } else {
2198    ///         None
2199    ///     }
2200    /// });
2201    /// assert_eq!(result, Ok(ptr));
2202    /// assert_eq!(some_ptr.load(Ordering::SeqCst), new);
2203    /// ```
2204    #[inline]
2205    #[cfg_attr(
2206        any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri),
2207        track_caller
2208    )]
2209    pub fn fetch_update<F>(
2210        &self,
2211        set_order: Ordering,
2212        fetch_order: Ordering,
2213        mut f: F,
2214    ) -> Result<*mut T, *mut T>
2215    where
2216        F: FnMut(*mut T) -> Option<*mut T>,
2217    {
2218        let mut prev = self.load(fetch_order);
2219        while let Some(next) = f(prev) {
2220            match self.compare_exchange_weak(prev, next, set_order, fetch_order) {
2221                x @ Ok(_) => return x,
2222                Err(next_prev) => prev = next_prev,
2223            }
2224        }
2225        Err(prev)
2226    }
2227    } // cfg_has_atomic_cas!
2228
2229    /// Offsets the pointer's address by adding `val` (in units of `T`),
2230    /// returning the previous pointer.
2231    ///
2232    /// This is equivalent to using [`wrapping_add`] to atomically perform the
2233    /// equivalent of `ptr = ptr.wrapping_add(val);`.
2234    ///
2235    /// This method operates in units of `T`, which means that it cannot be used
2236    /// to offset the pointer by an amount which is not a multiple of
2237    /// `size_of::<T>()`. This can sometimes be inconvenient, as you may want to
2238    /// work with a deliberately misaligned pointer. In such cases, you may use
2239    /// the [`fetch_byte_add`](Self::fetch_byte_add) method instead.
2240    ///
2241    /// `fetch_ptr_add` takes an [`Ordering`] argument which describes the
2242    /// memory ordering of this operation. All ordering modes are possible. Note
2243    /// that using [`Acquire`] makes the store part of this operation
2244    /// [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`].
2245    ///
2246    /// [`wrapping_add`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.wrapping_add
2247    ///
2248    /// # Examples
2249    ///
2250    /// ```
2251    /// # #![allow(unstable_name_collisions)]
2252    /// # #[allow(unused_imports)] use sptr::Strict as _; // strict provenance polyfill for old rustc
2253    /// use portable_atomic::{AtomicPtr, Ordering};
2254    ///
2255    /// let atom = AtomicPtr::<i64>::new(core::ptr::null_mut());
2256    /// assert_eq!(atom.fetch_ptr_add(1, Ordering::Relaxed).addr(), 0);
2257    /// // Note: units of `size_of::<i64>()`.
2258    /// assert_eq!(atom.load(Ordering::Relaxed).addr(), 8);
2259    /// ```
2260    #[inline]
2261    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
2262    pub fn fetch_ptr_add(&self, val: usize, order: Ordering) -> *mut T {
2263        self.fetch_byte_add(val.wrapping_mul(core::mem::size_of::<T>()), order)
2264    }
2265
2266    /// Offsets the pointer's address by subtracting `val` (in units of `T`),
2267    /// returning the previous pointer.
2268    ///
2269    /// This is equivalent to using [`wrapping_sub`] to atomically perform the
2270    /// equivalent of `ptr = ptr.wrapping_sub(val);`.
2271    ///
2272    /// This method operates in units of `T`, which means that it cannot be used
2273    /// to offset the pointer by an amount which is not a multiple of
2274    /// `size_of::<T>()`. This can sometimes be inconvenient, as you may want to
2275    /// work with a deliberately misaligned pointer. In such cases, you may use
2276    /// the [`fetch_byte_sub`](Self::fetch_byte_sub) method instead.
2277    ///
2278    /// `fetch_ptr_sub` takes an [`Ordering`] argument which describes the memory
2279    /// ordering of this operation. All ordering modes are possible. Note that
2280    /// using [`Acquire`] makes the store part of this operation [`Relaxed`],
2281    /// and using [`Release`] makes the load part [`Relaxed`].
2282    ///
2283    /// [`wrapping_sub`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.wrapping_sub
2284    ///
2285    /// # Examples
2286    ///
2287    /// ```
2288    /// use portable_atomic::{AtomicPtr, Ordering};
2289    ///
2290    /// let array = [1i32, 2i32];
2291    /// let atom = AtomicPtr::new(array.as_ptr().wrapping_add(1) as *mut _);
2292    ///
2293    /// assert!(core::ptr::eq(atom.fetch_ptr_sub(1, Ordering::Relaxed), &array[1]));
2294    /// assert!(core::ptr::eq(atom.load(Ordering::Relaxed), &array[0]));
2295    /// ```
2296    #[inline]
2297    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
2298    pub fn fetch_ptr_sub(&self, val: usize, order: Ordering) -> *mut T {
2299        self.fetch_byte_sub(val.wrapping_mul(core::mem::size_of::<T>()), order)
2300    }
2301
2302    /// Offsets the pointer's address by adding `val` *bytes*, returning the
2303    /// previous pointer.
2304    ///
2305    /// This is equivalent to using [`wrapping_add`] and [`cast`] to atomically
2306    /// perform `ptr = ptr.cast::<u8>().wrapping_add(val).cast::<T>()`.
2307    ///
2308    /// `fetch_byte_add` takes an [`Ordering`] argument which describes the
2309    /// memory ordering of this operation. All ordering modes are possible. Note
2310    /// that using [`Acquire`] makes the store part of this operation
2311    /// [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`].
2312    ///
2313    /// [`wrapping_add`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.wrapping_add
2314    /// [`cast`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.cast
2315    ///
2316    /// # Examples
2317    ///
2318    /// ```
2319    /// # #![allow(unstable_name_collisions)]
2320    /// # #[allow(unused_imports)] use sptr::Strict as _; // strict provenance polyfill for old rustc
2321    /// use portable_atomic::{AtomicPtr, Ordering};
2322    ///
2323    /// let atom = AtomicPtr::<i64>::new(core::ptr::null_mut());
2324    /// assert_eq!(atom.fetch_byte_add(1, Ordering::Relaxed).addr(), 0);
2325    /// // Note: in units of bytes, not `size_of::<i64>()`.
2326    /// assert_eq!(atom.load(Ordering::Relaxed).addr(), 1);
2327    /// ```
2328    #[inline]
2329    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
2330    pub fn fetch_byte_add(&self, val: usize, order: Ordering) -> *mut T {
2331        self.inner.fetch_byte_add(val, order)
2332    }
2333
2334    /// Offsets the pointer's address by subtracting `val` *bytes*, returning the
2335    /// previous pointer.
2336    ///
2337    /// This is equivalent to using [`wrapping_sub`] and [`cast`] to atomically
2338    /// perform `ptr = ptr.cast::<u8>().wrapping_sub(val).cast::<T>()`.
2339    ///
2340    /// `fetch_byte_sub` takes an [`Ordering`] argument which describes the
2341    /// memory ordering of this operation. All ordering modes are possible. Note
2342    /// that using [`Acquire`] makes the store part of this operation
2343    /// [`Relaxed`], and using [`Release`] makes the load part [`Relaxed`].
2344    ///
2345    /// [`wrapping_sub`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.wrapping_sub
2346    /// [`cast`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.cast
2347    ///
2348    /// # Examples
2349    ///
2350    /// ```
2351    /// # #![allow(unstable_name_collisions)]
2352    /// # #[allow(unused_imports)] use sptr::Strict as _; // strict provenance polyfill for old rustc
2353    /// use portable_atomic::{AtomicPtr, Ordering};
2354    ///
2355    /// let atom = AtomicPtr::<i64>::new(sptr::invalid_mut(1));
2356    /// assert_eq!(atom.fetch_byte_sub(1, Ordering::Relaxed).addr(), 1);
2357    /// assert_eq!(atom.load(Ordering::Relaxed).addr(), 0);
2358    /// ```
2359    #[inline]
2360    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
2361    pub fn fetch_byte_sub(&self, val: usize, order: Ordering) -> *mut T {
2362        self.inner.fetch_byte_sub(val, order)
2363    }
2364
2365    /// Performs a bitwise "or" operation on the address of the current pointer,
2366    /// and the argument `val`, and stores a pointer with provenance of the
2367    /// current pointer and the resulting address.
2368    ///
2369    /// This is equivalent to using [`map_addr`] to atomically perform
2370    /// `ptr = ptr.map_addr(|a| a | val)`. This can be used in tagged
2371    /// pointer schemes to atomically set tag bits.
2372    ///
2373    /// **Caveat**: This operation returns the previous value. To compute the
2374    /// stored value without losing provenance, you may use [`map_addr`]. For
2375    /// example: `a.fetch_or(val).map_addr(|a| a | val)`.
2376    ///
2377    /// `fetch_or` takes an [`Ordering`] argument which describes the memory
2378    /// ordering of this operation. All ordering modes are possible. Note that
2379    /// using [`Acquire`] makes the store part of this operation [`Relaxed`],
2380    /// and using [`Release`] makes the load part [`Relaxed`].
2381    ///
2382    /// This API and its claimed semantics are part of the Strict Provenance
2383    /// experiment, see the [module documentation for `ptr`][core::ptr] for
2384    /// details.
2385    ///
2386    /// [`map_addr`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.map_addr
2387    ///
2388    /// # Examples
2389    ///
2390    /// ```
2391    /// # #![allow(unstable_name_collisions)]
2392    /// # #[allow(unused_imports)] use sptr::Strict as _; // strict provenance polyfill for old rustc
2393    /// use portable_atomic::{AtomicPtr, Ordering};
2394    ///
2395    /// let pointer = &mut 3i64 as *mut i64;
2396    ///
2397    /// let atom = AtomicPtr::<i64>::new(pointer);
2398    /// // Tag the bottom bit of the pointer.
2399    /// assert_eq!(atom.fetch_or(1, Ordering::Relaxed).addr() & 1, 0);
2400    /// // Extract and untag.
2401    /// let tagged = atom.load(Ordering::Relaxed);
2402    /// assert_eq!(tagged.addr() & 1, 1);
2403    /// assert_eq!(tagged.map_addr(|p| p & !1), pointer);
2404    /// ```
2405    #[inline]
2406    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
2407    pub fn fetch_or(&self, val: usize, order: Ordering) -> *mut T {
2408        self.inner.fetch_or(val, order)
2409    }
2410
2411    /// Performs a bitwise "and" operation on the address of the current
2412    /// pointer, and the argument `val`, and stores a pointer with provenance of
2413    /// the current pointer and the resulting address.
2414    ///
2415    /// This is equivalent to using [`map_addr`] to atomically perform
2416    /// `ptr = ptr.map_addr(|a| a & val)`. This can be used in tagged
2417    /// pointer schemes to atomically unset tag bits.
2418    ///
2419    /// **Caveat**: This operation returns the previous value. To compute the
2420    /// stored value without losing provenance, you may use [`map_addr`]. For
2421    /// example: `a.fetch_and(val).map_addr(|a| a & val)`.
2422    ///
2423    /// `fetch_and` takes an [`Ordering`] argument which describes the memory
2424    /// ordering of this operation. All ordering modes are possible. Note that
2425    /// using [`Acquire`] makes the store part of this operation [`Relaxed`],
2426    /// and using [`Release`] makes the load part [`Relaxed`].
2427    ///
2428    /// This API and its claimed semantics are part of the Strict Provenance
2429    /// experiment, see the [module documentation for `ptr`][core::ptr] for
2430    /// details.
2431    ///
2432    /// [`map_addr`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.map_addr
2433    ///
2434    /// # Examples
2435    ///
2436    /// ```
2437    /// # #![allow(unstable_name_collisions)]
2438    /// # #[allow(unused_imports)] use sptr::Strict as _; // strict provenance polyfill for old rustc
2439    /// use portable_atomic::{AtomicPtr, Ordering};
2440    ///
2441    /// let pointer = &mut 3i64 as *mut i64;
2442    /// // A tagged pointer
2443    /// let atom = AtomicPtr::<i64>::new(pointer.map_addr(|a| a | 1));
2444    /// assert_eq!(atom.fetch_or(1, Ordering::Relaxed).addr() & 1, 1);
2445    /// // Untag, and extract the previously tagged pointer.
2446    /// let untagged = atom.fetch_and(!1, Ordering::Relaxed).map_addr(|a| a & !1);
2447    /// assert_eq!(untagged, pointer);
2448    /// ```
2449    #[inline]
2450    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
2451    pub fn fetch_and(&self, val: usize, order: Ordering) -> *mut T {
2452        self.inner.fetch_and(val, order)
2453    }
2454
2455    /// Performs a bitwise "xor" operation on the address of the current
2456    /// pointer, and the argument `val`, and stores a pointer with provenance of
2457    /// the current pointer and the resulting address.
2458    ///
2459    /// This is equivalent to using [`map_addr`] to atomically perform
2460    /// `ptr = ptr.map_addr(|a| a ^ val)`. This can be used in tagged
2461    /// pointer schemes to atomically toggle tag bits.
2462    ///
2463    /// **Caveat**: This operation returns the previous value. To compute the
2464    /// stored value without losing provenance, you may use [`map_addr`]. For
2465    /// example: `a.fetch_xor(val).map_addr(|a| a ^ val)`.
2466    ///
2467    /// `fetch_xor` takes an [`Ordering`] argument which describes the memory
2468    /// ordering of this operation. All ordering modes are possible. Note that
2469    /// using [`Acquire`] makes the store part of this operation [`Relaxed`],
2470    /// and using [`Release`] makes the load part [`Relaxed`].
2471    ///
2472    /// This API and its claimed semantics are part of the Strict Provenance
2473    /// experiment, see the [module documentation for `ptr`][core::ptr] for
2474    /// details.
2475    ///
2476    /// [`map_addr`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.map_addr
2477    ///
2478    /// # Examples
2479    ///
2480    /// ```
2481    /// # #![allow(unstable_name_collisions)]
2482    /// # #[allow(unused_imports)] use sptr::Strict as _; // strict provenance polyfill for old rustc
2483    /// use portable_atomic::{AtomicPtr, Ordering};
2484    ///
2485    /// let pointer = &mut 3i64 as *mut i64;
2486    /// let atom = AtomicPtr::<i64>::new(pointer);
2487    ///
2488    /// // Toggle a tag bit on the pointer.
2489    /// atom.fetch_xor(1, Ordering::Relaxed);
2490    /// assert_eq!(atom.load(Ordering::Relaxed).addr() & 1, 1);
2491    /// ```
2492    #[inline]
2493    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
2494    pub fn fetch_xor(&self, val: usize, order: Ordering) -> *mut T {
2495        self.inner.fetch_xor(val, order)
2496    }
2497
2498    /// Sets the bit at the specified bit-position to 1.
2499    ///
2500    /// Returns `true` if the specified bit was previously set to 1.
2501    ///
2502    /// `bit_set` takes an [`Ordering`] argument which describes the memory ordering
2503    /// of this operation. All ordering modes are possible. Note that using
2504    /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
2505    /// using [`Release`] makes the load part [`Relaxed`].
2506    ///
2507    /// This corresponds to x86's `lock bts`, and the implementation calls them on x86/x86_64.
2508    ///
2509    /// # Examples
2510    ///
2511    /// ```
2512    /// # #![allow(unstable_name_collisions)]
2513    /// # #[allow(unused_imports)] use sptr::Strict as _; // strict provenance polyfill for old rustc
2514    /// use portable_atomic::{AtomicPtr, Ordering};
2515    ///
2516    /// let pointer = &mut 3i64 as *mut i64;
2517    ///
2518    /// let atom = AtomicPtr::<i64>::new(pointer);
2519    /// // Tag the bottom bit of the pointer.
2520    /// assert!(!atom.bit_set(0, Ordering::Relaxed));
2521    /// // Extract and untag.
2522    /// let tagged = atom.load(Ordering::Relaxed);
2523    /// assert_eq!(tagged.addr() & 1, 1);
2524    /// assert_eq!(tagged.map_addr(|p| p & !1), pointer);
2525    /// ```
2526    #[inline]
2527    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
2528    pub fn bit_set(&self, bit: u32, order: Ordering) -> bool {
2529        self.inner.bit_set(bit, order)
2530    }
2531
2532    /// Clears the bit at the specified bit-position to 0.
2533    ///
2534    /// Returns `true` if the specified bit was previously set to 1.
2535    ///
2536    /// `bit_clear` takes an [`Ordering`] argument which describes the memory ordering
2537    /// of this operation. All ordering modes are possible. Note that using
2538    /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
2539    /// using [`Release`] makes the load part [`Relaxed`].
2540    ///
2541    /// This corresponds to x86's `lock btr`, and the implementation calls them on x86/x86_64.
2542    ///
2543    /// # Examples
2544    ///
2545    /// ```
2546    /// # #![allow(unstable_name_collisions)]
2547    /// # #[allow(unused_imports)] use sptr::Strict as _; // strict provenance polyfill for old rustc
2548    /// use portable_atomic::{AtomicPtr, Ordering};
2549    ///
2550    /// let pointer = &mut 3i64 as *mut i64;
2551    /// // A tagged pointer
2552    /// let atom = AtomicPtr::<i64>::new(pointer.map_addr(|a| a | 1));
2553    /// assert!(atom.bit_set(0, Ordering::Relaxed));
2554    /// // Untag
2555    /// assert!(atom.bit_clear(0, Ordering::Relaxed));
2556    /// ```
2557    #[inline]
2558    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
2559    pub fn bit_clear(&self, bit: u32, order: Ordering) -> bool {
2560        self.inner.bit_clear(bit, order)
2561    }
2562
2563    /// Toggles the bit at the specified bit-position.
2564    ///
2565    /// Returns `true` if the specified bit was previously set to 1.
2566    ///
2567    /// `bit_toggle` takes an [`Ordering`] argument which describes the memory ordering
2568    /// of this operation. All ordering modes are possible. Note that using
2569    /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
2570    /// using [`Release`] makes the load part [`Relaxed`].
2571    ///
2572    /// This corresponds to x86's `lock btc`, and the implementation calls them on x86/x86_64.
2573    ///
2574    /// # Examples
2575    ///
2576    /// ```
2577    /// # #![allow(unstable_name_collisions)]
2578    /// # #[allow(unused_imports)] use sptr::Strict as _; // strict provenance polyfill for old rustc
2579    /// use portable_atomic::{AtomicPtr, Ordering};
2580    ///
2581    /// let pointer = &mut 3i64 as *mut i64;
2582    /// let atom = AtomicPtr::<i64>::new(pointer);
2583    ///
2584    /// // Toggle a tag bit on the pointer.
2585    /// atom.bit_toggle(0, Ordering::Relaxed);
2586    /// assert_eq!(atom.load(Ordering::Relaxed).addr() & 1, 1);
2587    /// ```
2588    #[inline]
2589    #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
2590    pub fn bit_toggle(&self, bit: u32, order: Ordering) -> bool {
2591        self.inner.bit_toggle(bit, order)
2592    }
2593    } // cfg_has_atomic_cas_or_amo32!
2594
2595    const_fn! {
2596        const_if: #[cfg(not(portable_atomic_no_const_raw_ptr_deref))];
2597        /// Returns a mutable pointer to the underlying pointer.
2598        ///
2599        /// Returning an `*mut` pointer from a shared reference to this atomic is
2600        /// safe because the atomic types work with interior mutability. Any use of
2601        /// the returned raw pointer requires an `unsafe` block and has to uphold
2602        /// the safety requirements. If there is concurrent access, note the following
2603        /// additional safety requirements:
2604        ///
2605        /// - If this atomic type is [lock-free](Self::is_lock_free), any concurrent
2606        ///   operations on it must be atomic.
2607        /// - Otherwise, any concurrent operations on it must be compatible with
2608        ///   operations performed by this atomic type.
2609        ///
2610        /// This is `const fn` on Rust 1.58+.
2611        #[inline]
2612        pub const fn as_ptr(&self) -> *mut *mut T {
2613            self.inner.as_ptr()
2614        }
2615    }
2616}
2617// See https://github.com/taiki-e/portable-atomic/issues/180
2618#[cfg(not(feature = "require-cas"))]
2619cfg_no_atomic_cas! {
2620#[doc(hidden)]
2621#[allow(unused_variables, clippy::unused_self, clippy::extra_unused_lifetimes)]
2622impl<'a, T: 'a> AtomicPtr<T> {
2623    cfg_no_atomic_cas_or_amo32! {
2624    #[inline]
2625    pub fn swap(&self, ptr: *mut T, order: Ordering) -> *mut T
2626    where
2627        &'a Self: HasSwap,
2628    {
2629        unimplemented!()
2630    }
2631    } // cfg_no_atomic_cas_or_amo32!
2632    #[inline]
2633    pub fn compare_exchange(
2634        &self,
2635        current: *mut T,
2636        new: *mut T,
2637        success: Ordering,
2638        failure: Ordering,
2639    ) -> Result<*mut T, *mut T>
2640    where
2641        &'a Self: HasCompareExchange,
2642    {
2643        unimplemented!()
2644    }
2645    #[inline]
2646    pub fn compare_exchange_weak(
2647        &self,
2648        current: *mut T,
2649        new: *mut T,
2650        success: Ordering,
2651        failure: Ordering,
2652    ) -> Result<*mut T, *mut T>
2653    where
2654        &'a Self: HasCompareExchangeWeak,
2655    {
2656        unimplemented!()
2657    }
2658    #[inline]
2659    pub fn fetch_update<F>(
2660        &self,
2661        set_order: Ordering,
2662        fetch_order: Ordering,
2663        f: F,
2664    ) -> Result<*mut T, *mut T>
2665    where
2666        F: FnMut(*mut T) -> Option<*mut T>,
2667        &'a Self: HasFetchUpdate,
2668    {
2669        unimplemented!()
2670    }
2671    cfg_no_atomic_cas_or_amo32! {
2672    #[inline]
2673    pub fn fetch_ptr_add(&self, val: usize, order: Ordering) -> *mut T
2674    where
2675        &'a Self: HasFetchPtrAdd,
2676    {
2677        unimplemented!()
2678    }
2679    #[inline]
2680    pub fn fetch_ptr_sub(&self, val: usize, order: Ordering) -> *mut T
2681    where
2682        &'a Self: HasFetchPtrSub,
2683    {
2684        unimplemented!()
2685    }
2686    #[inline]
2687    pub fn fetch_byte_add(&self, val: usize, order: Ordering) -> *mut T
2688    where
2689        &'a Self: HasFetchByteAdd,
2690    {
2691        unimplemented!()
2692    }
2693    #[inline]
2694    pub fn fetch_byte_sub(&self, val: usize, order: Ordering) -> *mut T
2695    where
2696        &'a Self: HasFetchByteSub,
2697    {
2698        unimplemented!()
2699    }
2700    #[inline]
2701    pub fn fetch_or(&self, val: usize, order: Ordering) -> *mut T
2702    where
2703        &'a Self: HasFetchOr,
2704    {
2705        unimplemented!()
2706    }
2707    #[inline]
2708    pub fn fetch_and(&self, val: usize, order: Ordering) -> *mut T
2709    where
2710        &'a Self: HasFetchAnd,
2711    {
2712        unimplemented!()
2713    }
2714    #[inline]
2715    pub fn fetch_xor(&self, val: usize, order: Ordering) -> *mut T
2716    where
2717        &'a Self: HasFetchXor,
2718    {
2719        unimplemented!()
2720    }
2721    #[inline]
2722    pub fn bit_set(&self, bit: u32, order: Ordering) -> bool
2723    where
2724        &'a Self: HasBitSet,
2725    {
2726        unimplemented!()
2727    }
2728    #[inline]
2729    pub fn bit_clear(&self, bit: u32, order: Ordering) -> bool
2730    where
2731        &'a Self: HasBitClear,
2732    {
2733        unimplemented!()
2734    }
2735    #[inline]
2736    pub fn bit_toggle(&self, bit: u32, order: Ordering) -> bool
2737    where
2738        &'a Self: HasBitToggle,
2739    {
2740        unimplemented!()
2741    }
2742    } // cfg_no_atomic_cas_or_amo32!
2743}
2744} // cfg_no_atomic_cas!
2745} // cfg_has_atomic_ptr!
2746
2747macro_rules! atomic_int {
2748    // Atomic{I,U}* impls
2749    ($atomic_type:ident, $int_type:ident, $align:literal,
2750        $cfg_has_atomic_cas_or_amo32_or_8:ident, $cfg_no_atomic_cas_or_amo32_or_8:ident
2751        $(, #[$cfg_float:meta] $atomic_float_type:ident, $float_type:ident)?
2752    ) => {
2753        doc_comment! {
2754            concat!("An integer type which can be safely shared between threads.
2755
2756This type has the same in-memory representation as the underlying integer type,
2757[`", stringify!($int_type), "`].
2758
2759If the compiler and the platform support atomic loads and stores of [`", stringify!($int_type),
2760"`], this type is a wrapper for the standard library's `", stringify!($atomic_type),
2761"`. If the platform supports it but the compiler does not, atomic operations are implemented using
2762inline assembly. Otherwise synchronizes using global locks.
2763You can call [`", stringify!($atomic_type), "::is_lock_free()`] to check whether
2764atomic instructions or locks will be used.
2765"
2766            ),
2767            // We can use #[repr(transparent)] here, but #[repr(C, align(N))]
2768            // will show clearer docs.
2769            #[repr(C, align($align))]
2770            pub struct $atomic_type {
2771                inner: imp::$atomic_type,
2772            }
2773        }
2774
2775        impl Default for $atomic_type {
2776            #[inline]
2777            fn default() -> Self {
2778                Self::new($int_type::default())
2779            }
2780        }
2781
2782        impl From<$int_type> for $atomic_type {
2783            #[inline]
2784            fn from(v: $int_type) -> Self {
2785                Self::new(v)
2786            }
2787        }
2788
2789        // UnwindSafe is implicitly implemented.
2790        #[cfg(not(portable_atomic_no_core_unwind_safe))]
2791        impl core::panic::RefUnwindSafe for $atomic_type {}
2792        #[cfg(all(portable_atomic_no_core_unwind_safe, feature = "std"))]
2793        impl std::panic::RefUnwindSafe for $atomic_type {}
2794
2795        impl_debug_and_serde!($atomic_type);
2796
2797        impl $atomic_type {
2798            doc_comment! {
2799                concat!(
2800                    "Creates a new atomic integer.
2801
2802# Examples
2803
2804```
2805use portable_atomic::", stringify!($atomic_type), ";
2806
2807let atomic_forty_two = ", stringify!($atomic_type), "::new(42);
2808```"
2809                ),
2810                #[inline]
2811                #[must_use]
2812                pub const fn new(v: $int_type) -> Self {
2813                    static_assert_layout!($atomic_type, $int_type);
2814                    Self { inner: imp::$atomic_type::new(v) }
2815                }
2816            }
2817
2818            // TODO: update docs based on https://github.com/rust-lang/rust/pull/116762
2819            #[cfg(not(portable_atomic_no_const_raw_ptr_deref))]
2820            doc_comment! {
2821                concat!("Creates a new reference to an atomic integer from a pointer.
2822
2823This is `const fn` on Rust 1.58+.
2824
2825# Safety
2826
2827* `ptr` must be aligned to `align_of::<", stringify!($atomic_type), ">()` (note that on some platforms this
2828  can be bigger than `align_of::<", stringify!($int_type), ">()`).
2829* `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`.
2830* If this atomic type is [lock-free](Self::is_lock_free), non-atomic accesses to the value
2831  behind `ptr` must have a happens-before relationship with atomic accesses via
2832  the returned value (or vice-versa).
2833  * In other words, time periods where the value is accessed atomically may not
2834    overlap with periods where the value is accessed non-atomically.
2835  * This requirement is trivially satisfied if `ptr` is never used non-atomically
2836    for the duration of lifetime `'a`. Most use cases should be able to follow
2837    this guideline.
2838  * This requirement is also trivially satisfied if all accesses (atomic or not) are
2839    done from the same thread.
2840* If this atomic type is *not* lock-free:
2841  * Any accesses to the value behind `ptr` must have a happens-before relationship
2842    with accesses via the returned value (or vice-versa).
2843  * Any concurrent accesses to the value behind `ptr` for the duration of lifetime `'a` must
2844    be compatible with operations performed by this atomic type.
2845* This method must not be used to create overlapping or mixed-size atomic
2846  accesses, as these are not supported by the memory model.
2847
2848[valid]: core::ptr#safety"),
2849                #[inline]
2850                #[must_use]
2851                pub const unsafe fn from_ptr<'a>(ptr: *mut $int_type) -> &'a Self {
2852                    #[allow(clippy::cast_ptr_alignment)]
2853                    // SAFETY: guaranteed by the caller
2854                    unsafe { &*(ptr as *mut Self as *const Self) }
2855                }
2856            }
2857            #[cfg(portable_atomic_no_const_raw_ptr_deref)]
2858            doc_comment! {
2859                concat!("Creates a new reference to an atomic integer from a pointer.
2860
2861This is `const fn` on Rust 1.58+.
2862
2863# Safety
2864
2865* `ptr` must be aligned to `align_of::<", stringify!($atomic_type), ">()` (note that on some platforms this
2866  can be bigger than `align_of::<", stringify!($int_type), ">()`).
2867* `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`.
2868* If this atomic type is [lock-free](Self::is_lock_free), non-atomic accesses to the value
2869  behind `ptr` must have a happens-before relationship with atomic accesses via
2870  the returned value (or vice-versa).
2871  * In other words, time periods where the value is accessed atomically may not
2872    overlap with periods where the value is accessed non-atomically.
2873  * This requirement is trivially satisfied if `ptr` is never used non-atomically
2874    for the duration of lifetime `'a`. Most use cases should be able to follow
2875    this guideline.
2876  * This requirement is also trivially satisfied if all accesses (atomic or not) are
2877    done from the same thread.
2878* If this atomic type is *not* lock-free:
2879  * Any accesses to the value behind `ptr` must have a happens-before relationship
2880    with accesses via the returned value (or vice-versa).
2881  * Any concurrent accesses to the value behind `ptr` for the duration of lifetime `'a` must
2882    be compatible with operations performed by this atomic type.
2883* This method must not be used to create overlapping or mixed-size atomic
2884  accesses, as these are not supported by the memory model.
2885
2886[valid]: core::ptr#safety"),
2887                #[inline]
2888                #[must_use]
2889                pub unsafe fn from_ptr<'a>(ptr: *mut $int_type) -> &'a Self {
2890                    #[allow(clippy::cast_ptr_alignment)]
2891                    // SAFETY: guaranteed by the caller
2892                    unsafe { &*(ptr as *mut Self as *const Self) }
2893                }
2894            }
2895
2896            doc_comment! {
2897                concat!("Returns `true` if operations on values of this type are lock-free.
2898
2899If the compiler or the platform doesn't support the necessary
2900atomic instructions, global locks for every potentially
2901concurrent atomic operation will be used.
2902
2903This function is guaranteed to always return the same result.
2904
2905# Examples
2906
2907```
2908use portable_atomic::", stringify!($atomic_type), ";
2909
2910let is_lock_free = ", stringify!($atomic_type), "::is_lock_free();
2911```"),
2912                #[inline]
2913                #[must_use]
2914                pub fn is_lock_free() -> bool {
2915                    <imp::$atomic_type>::is_lock_free()
2916                }
2917            }
2918
2919            doc_comment! {
2920                concat!("Returns `true` if operations on values of this type are lock-free.
2921
2922If the compiler or the platform doesn't support the necessary
2923atomic instructions, global locks for every potentially
2924concurrent atomic operation will be used.
2925
2926**Note:** If the atomic operation relies on dynamic CPU feature detection,
2927this type may be lock-free even if the function returns false.
2928
2929# Examples
2930
2931```
2932use portable_atomic::", stringify!($atomic_type), ";
2933
2934const IS_ALWAYS_LOCK_FREE: bool = ", stringify!($atomic_type), "::is_always_lock_free();
2935```"),
2936                #[inline]
2937                #[must_use]
2938                pub const fn is_always_lock_free() -> bool {
2939                    <imp::$atomic_type>::IS_ALWAYS_LOCK_FREE
2940                }
2941            }
2942            #[cfg(test)]
2943            #[cfg_attr(all(valgrind, target_arch = "powerpc64"), allow(dead_code))] // TODO(powerpc64): Hang (as of Valgrind 3.26)
2944            const IS_ALWAYS_LOCK_FREE: bool = Self::is_always_lock_free();
2945
2946            #[cfg(not(portable_atomic_no_const_mut_refs))]
2947            doc_comment! {
2948                concat!("Returns a mutable reference to the underlying integer.\n
2949This is safe because the mutable reference guarantees that no other threads are
2950concurrently accessing the atomic data.
2951
2952This is `const fn` on Rust 1.83+.
2953
2954# Examples
2955
2956```
2957use portable_atomic::{", stringify!($atomic_type), ", Ordering};
2958
2959let mut some_var = ", stringify!($atomic_type), "::new(10);
2960assert_eq!(*some_var.get_mut(), 10);
2961*some_var.get_mut() = 5;
2962assert_eq!(some_var.load(Ordering::SeqCst), 5);
2963```"),
2964                #[inline]
2965                pub const fn get_mut(&mut self) -> &mut $int_type {
2966                    // SAFETY: the mutable reference guarantees unique ownership.
2967                    // (core::sync::atomic::Atomic*::get_mut is not const yet)
2968                    unsafe { &mut *self.as_ptr() }
2969                }
2970            }
2971            #[cfg(portable_atomic_no_const_mut_refs)]
2972            doc_comment! {
2973                concat!("Returns a mutable reference to the underlying integer.\n
2974This is safe because the mutable reference guarantees that no other threads are
2975concurrently accessing the atomic data.
2976
2977This is `const fn` on Rust 1.83+.
2978
2979# Examples
2980
2981```
2982use portable_atomic::{", stringify!($atomic_type), ", Ordering};
2983
2984let mut some_var = ", stringify!($atomic_type), "::new(10);
2985assert_eq!(*some_var.get_mut(), 10);
2986*some_var.get_mut() = 5;
2987assert_eq!(some_var.load(Ordering::SeqCst), 5);
2988```"),
2989                #[inline]
2990                pub fn get_mut(&mut self) -> &mut $int_type {
2991                    // SAFETY: the mutable reference guarantees unique ownership.
2992                    unsafe { &mut *self.as_ptr() }
2993                }
2994            }
2995
2996            // TODO: Add from_mut/get_mut_slice/from_mut_slice once it is stable on std atomic types.
2997            // https://github.com/rust-lang/rust/issues/76314
2998
2999            #[cfg(not(portable_atomic_no_const_transmute))]
3000            doc_comment! {
3001                concat!("Consumes the atomic and returns the contained value.
3002
3003This is safe because passing `self` by value guarantees that no other threads are
3004concurrently accessing the atomic data.
3005
3006This is `const fn` on Rust 1.56+.
3007
3008# Examples
3009
3010```
3011use portable_atomic::", stringify!($atomic_type), ";
3012
3013let some_var = ", stringify!($atomic_type), "::new(5);
3014assert_eq!(some_var.into_inner(), 5);
3015```"),
3016                #[inline]
3017                pub const fn into_inner(self) -> $int_type {
3018                    // SAFETY: $atomic_type and $int_type have the same size and in-memory representations,
3019                    // so they can be safely transmuted.
3020                    // (const UnsafeCell::into_inner is unstable)
3021                    unsafe { core::mem::transmute(self) }
3022                }
3023            }
3024            #[cfg(portable_atomic_no_const_transmute)]
3025            doc_comment! {
3026                concat!("Consumes the atomic and returns the contained value.
3027
3028This is safe because passing `self` by value guarantees that no other threads are
3029concurrently accessing the atomic data.
3030
3031This is `const fn` on Rust 1.56+.
3032
3033# Examples
3034
3035```
3036use portable_atomic::", stringify!($atomic_type), ";
3037
3038let some_var = ", stringify!($atomic_type), "::new(5);
3039assert_eq!(some_var.into_inner(), 5);
3040```"),
3041                #[inline]
3042                pub fn into_inner(self) -> $int_type {
3043                    // SAFETY: $atomic_type and $int_type have the same size and in-memory representations,
3044                    // so they can be safely transmuted.
3045                    // (const UnsafeCell::into_inner is unstable)
3046                    unsafe { core::mem::transmute(self) }
3047                }
3048            }
3049
3050            doc_comment! {
3051                concat!("Loads a value from the atomic integer.
3052
3053`load` takes an [`Ordering`] argument which describes the memory ordering of this operation.
3054Possible values are [`SeqCst`], [`Acquire`] and [`Relaxed`].
3055
3056# Panics
3057
3058Panics if `order` is [`Release`] or [`AcqRel`].
3059
3060# Examples
3061
3062```
3063use portable_atomic::{", stringify!($atomic_type), ", Ordering};
3064
3065let some_var = ", stringify!($atomic_type), "::new(5);
3066
3067assert_eq!(some_var.load(Ordering::Relaxed), 5);
3068```"),
3069                #[inline]
3070                #[cfg_attr(
3071                    any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri),
3072                    track_caller
3073                )]
3074                pub fn load(&self, order: Ordering) -> $int_type {
3075                    self.inner.load(order)
3076                }
3077            }
3078
3079            doc_comment! {
3080                concat!("Stores a value into the atomic integer.
3081
3082`store` takes an [`Ordering`] argument which describes the memory ordering of this operation.
3083Possible values are [`SeqCst`], [`Release`] and [`Relaxed`].
3084
3085# Panics
3086
3087Panics if `order` is [`Acquire`] or [`AcqRel`].
3088
3089# Examples
3090
3091```
3092use portable_atomic::{", stringify!($atomic_type), ", Ordering};
3093
3094let some_var = ", stringify!($atomic_type), "::new(5);
3095
3096some_var.store(10, Ordering::Relaxed);
3097assert_eq!(some_var.load(Ordering::Relaxed), 10);
3098```"),
3099                #[inline]
3100                #[cfg_attr(
3101                    any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri),
3102                    track_caller
3103                )]
3104                pub fn store(&self, val: $int_type, order: Ordering) {
3105                    self.inner.store(val, order)
3106                }
3107            }
3108
3109            cfg_has_atomic_cas_or_amo32! {
3110            $cfg_has_atomic_cas_or_amo32_or_8! {
3111            doc_comment! {
3112                concat!("Stores a value into the atomic integer, returning the previous value.
3113
3114`swap` takes an [`Ordering`] argument which describes the memory ordering
3115of this operation. All ordering modes are possible. Note that using
3116[`Acquire`] makes the store part of this operation [`Relaxed`], and
3117using [`Release`] makes the load part [`Relaxed`].
3118
3119# Examples
3120
3121```
3122use portable_atomic::{", stringify!($atomic_type), ", Ordering};
3123
3124let some_var = ", stringify!($atomic_type), "::new(5);
3125
3126assert_eq!(some_var.swap(10, Ordering::Relaxed), 5);
3127```"),
3128                #[inline]
3129                #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
3130                pub fn swap(&self, val: $int_type, order: Ordering) -> $int_type {
3131                    self.inner.swap(val, order)
3132                }
3133            }
3134            } // $cfg_has_atomic_cas_or_amo32_or_8!
3135
3136            cfg_has_atomic_cas! {
3137            doc_comment! {
3138                concat!("Stores a value into the atomic integer if the current value is the same as
3139the `current` value.
3140
3141The return value is a result indicating whether the new value was written and
3142containing the previous value. On success this value is guaranteed to be equal to
3143`current`.
3144
3145`compare_exchange` takes two [`Ordering`] arguments to describe the memory
3146ordering of this operation. `success` describes the required ordering for the
3147read-modify-write operation that takes place if the comparison with `current` succeeds.
3148`failure` describes the required ordering for the load operation that takes place when
3149the comparison fails. Using [`Acquire`] as success ordering makes the store part
3150of this operation [`Relaxed`], and using [`Release`] makes the successful load
3151[`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
3152
3153# Panics
3154
3155Panics if `failure` is [`Release`], [`AcqRel`].
3156
3157# Examples
3158
3159```
3160use portable_atomic::{", stringify!($atomic_type), ", Ordering};
3161
3162let some_var = ", stringify!($atomic_type), "::new(5);
3163
3164assert_eq!(
3165    some_var.compare_exchange(5, 10, Ordering::Acquire, Ordering::Relaxed),
3166    Ok(5),
3167);
3168assert_eq!(some_var.load(Ordering::Relaxed), 10);
3169
3170assert_eq!(
3171    some_var.compare_exchange(6, 12, Ordering::SeqCst, Ordering::Acquire),
3172    Err(10),
3173);
3174assert_eq!(some_var.load(Ordering::Relaxed), 10);
3175```"),
3176                #[cfg_attr(docsrs, doc(alias = "compare_and_swap"))]
3177                #[inline]
3178                #[cfg_attr(
3179                    any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri),
3180                    track_caller
3181                )]
3182                pub fn compare_exchange(
3183                    &self,
3184                    current: $int_type,
3185                    new: $int_type,
3186                    success: Ordering,
3187                    failure: Ordering,
3188                ) -> Result<$int_type, $int_type> {
3189                    self.inner.compare_exchange(current, new, success, failure)
3190                }
3191            }
3192
3193            doc_comment! {
3194                concat!("Stores a value into the atomic integer if the current value is the same as
3195the `current` value.
3196Unlike [`compare_exchange`](Self::compare_exchange)
3197this function is allowed to spuriously fail even
3198when the comparison succeeds, which can result in more efficient code on some
3199platforms. The return value is a result indicating whether the new value was
3200written and containing the previous value.
3201
3202`compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory
3203ordering of this operation. `success` describes the required ordering for the
3204read-modify-write operation that takes place if the comparison with `current` succeeds.
3205`failure` describes the required ordering for the load operation that takes place when
3206the comparison fails. Using [`Acquire`] as success ordering makes the store part
3207of this operation [`Relaxed`], and using [`Release`] makes the successful load
3208[`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
3209
3210# Panics
3211
3212Panics if `failure` is [`Release`], [`AcqRel`].
3213
3214# Examples
3215
3216```
3217use portable_atomic::{", stringify!($atomic_type), ", Ordering};
3218
3219let val = ", stringify!($atomic_type), "::new(4);
3220
3221let mut old = val.load(Ordering::Relaxed);
3222loop {
3223    let new = old * 2;
3224    match val.compare_exchange_weak(old, new, Ordering::SeqCst, Ordering::Relaxed) {
3225        Ok(_) => break,
3226        Err(x) => old = x,
3227    }
3228}
3229```"),
3230                #[cfg_attr(docsrs, doc(alias = "compare_and_swap"))]
3231                #[inline]
3232                #[cfg_attr(
3233                    any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri),
3234                    track_caller
3235                )]
3236                pub fn compare_exchange_weak(
3237                    &self,
3238                    current: $int_type,
3239                    new: $int_type,
3240                    success: Ordering,
3241                    failure: Ordering,
3242                ) -> Result<$int_type, $int_type> {
3243                    self.inner.compare_exchange_weak(current, new, success, failure)
3244                }
3245            }
3246            } // cfg_has_atomic_cas!
3247
3248            $cfg_has_atomic_cas_or_amo32_or_8! {
3249            doc_comment! {
3250                concat!("Adds to the current value, returning the previous value.
3251
3252This operation wraps around on overflow.
3253
3254`fetch_add` takes an [`Ordering`] argument which describes the memory ordering
3255of this operation. All ordering modes are possible. Note that using
3256[`Acquire`] makes the store part of this operation [`Relaxed`], and
3257using [`Release`] makes the load part [`Relaxed`].
3258
3259# Examples
3260
3261```
3262use portable_atomic::{", stringify!($atomic_type), ", Ordering};
3263
3264let foo = ", stringify!($atomic_type), "::new(0);
3265assert_eq!(foo.fetch_add(10, Ordering::SeqCst), 0);
3266assert_eq!(foo.load(Ordering::SeqCst), 10);
3267```"),
3268                #[inline]
3269                #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
3270                pub fn fetch_add(&self, val: $int_type, order: Ordering) -> $int_type {
3271                    self.inner.fetch_add(val, order)
3272                }
3273            }
3274
3275            doc_comment! {
3276                concat!("Adds to the current value.
3277
3278This operation wraps around on overflow.
3279
3280Unlike `fetch_add`, this does not return the previous value.
3281
3282`add` takes an [`Ordering`] argument which describes the memory ordering
3283of this operation. All ordering modes are possible. Note that using
3284[`Acquire`] makes the store part of this operation [`Relaxed`], and
3285using [`Release`] makes the load part [`Relaxed`].
3286
3287This function may generate more efficient code than `fetch_add` on some platforms.
3288
3289- MSP430: `add` instead of disabling interrupts ({8,16}-bit atomics)
3290
3291# Examples
3292
3293```
3294use portable_atomic::{", stringify!($atomic_type), ", Ordering};
3295
3296let foo = ", stringify!($atomic_type), "::new(0);
3297foo.add(10, Ordering::SeqCst);
3298assert_eq!(foo.load(Ordering::SeqCst), 10);
3299```"),
3300                #[inline]
3301                #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
3302                pub fn add(&self, val: $int_type, order: Ordering) {
3303                    self.inner.add(val, order);
3304                }
3305            }
3306
3307            doc_comment! {
3308                concat!("Subtracts from the current value, returning the previous value.
3309
3310This operation wraps around on overflow.
3311
3312`fetch_sub` takes an [`Ordering`] argument which describes the memory ordering
3313of this operation. All ordering modes are possible. Note that using
3314[`Acquire`] makes the store part of this operation [`Relaxed`], and
3315using [`Release`] makes the load part [`Relaxed`].
3316
3317# Examples
3318
3319```
3320use portable_atomic::{", stringify!($atomic_type), ", Ordering};
3321
3322let foo = ", stringify!($atomic_type), "::new(20);
3323assert_eq!(foo.fetch_sub(10, Ordering::SeqCst), 20);
3324assert_eq!(foo.load(Ordering::SeqCst), 10);
3325```"),
3326                #[inline]
3327                #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
3328                pub fn fetch_sub(&self, val: $int_type, order: Ordering) -> $int_type {
3329                    self.inner.fetch_sub(val, order)
3330                }
3331            }
3332
3333            doc_comment! {
3334                concat!("Subtracts from the current value.
3335
3336This operation wraps around on overflow.
3337
3338Unlike `fetch_sub`, this does not return the previous value.
3339
3340`sub` takes an [`Ordering`] argument which describes the memory ordering
3341of this operation. All ordering modes are possible. Note that using
3342[`Acquire`] makes the store part of this operation [`Relaxed`], and
3343using [`Release`] makes the load part [`Relaxed`].
3344
3345This function may generate more efficient code than `fetch_sub` on some platforms.
3346
3347- MSP430: `sub` instead of disabling interrupts ({8,16}-bit atomics)
3348
3349# Examples
3350
3351```
3352use portable_atomic::{", stringify!($atomic_type), ", Ordering};
3353
3354let foo = ", stringify!($atomic_type), "::new(20);
3355foo.sub(10, Ordering::SeqCst);
3356assert_eq!(foo.load(Ordering::SeqCst), 10);
3357```"),
3358                #[inline]
3359                #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
3360                pub fn sub(&self, val: $int_type, order: Ordering) {
3361                    self.inner.sub(val, order);
3362                }
3363            }
3364            } // $cfg_has_atomic_cas_or_amo32_or_8!
3365
3366            doc_comment! {
3367                concat!("Bitwise \"and\" with the current value.
3368
3369Performs a bitwise \"and\" operation on the current value and the argument `val`, and
3370sets the new value to the result.
3371
3372Returns the previous value.
3373
3374`fetch_and` takes an [`Ordering`] argument which describes the memory ordering
3375of this operation. All ordering modes are possible. Note that using
3376[`Acquire`] makes the store part of this operation [`Relaxed`], and
3377using [`Release`] makes the load part [`Relaxed`].
3378
3379# Examples
3380
3381```
3382use portable_atomic::{", stringify!($atomic_type), ", Ordering};
3383
3384let foo = ", stringify!($atomic_type), "::new(0b101101);
3385assert_eq!(foo.fetch_and(0b110011, Ordering::SeqCst), 0b101101);
3386assert_eq!(foo.load(Ordering::SeqCst), 0b100001);
3387```"),
3388                #[inline]
3389                #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
3390                pub fn fetch_and(&self, val: $int_type, order: Ordering) -> $int_type {
3391                    self.inner.fetch_and(val, order)
3392                }
3393            }
3394
3395            doc_comment! {
3396                concat!("Bitwise \"and\" with the current value.
3397
3398Performs a bitwise \"and\" operation on the current value and the argument `val`, and
3399sets the new value to the result.
3400
3401Unlike `fetch_and`, this does not return the previous value.
3402
3403`and` takes an [`Ordering`] argument which describes the memory ordering
3404of this operation. All ordering modes are possible. Note that using
3405[`Acquire`] makes the store part of this operation [`Relaxed`], and
3406using [`Release`] makes the load part [`Relaxed`].
3407
3408This function may generate more efficient code than `fetch_and` on some platforms.
3409
3410- x86/x86_64: `lock and` instead of `cmpxchg` loop ({8,16,32}-bit atomics on x86, but additionally 64-bit atomics on x86_64)
3411- MSP430: `and` instead of disabling interrupts ({8,16}-bit atomics)
3412
3413Note: On x86/x86_64, the use of either function should not usually
3414affect the generated code, because LLVM can properly optimize the case
3415where the result is unused.
3416
3417# Examples
3418
3419```
3420use portable_atomic::{", stringify!($atomic_type), ", Ordering};
3421
3422let foo = ", stringify!($atomic_type), "::new(0b101101);
3423assert_eq!(foo.fetch_and(0b110011, Ordering::SeqCst), 0b101101);
3424assert_eq!(foo.load(Ordering::SeqCst), 0b100001);
3425```"),
3426                #[inline]
3427                #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
3428                pub fn and(&self, val: $int_type, order: Ordering) {
3429                    self.inner.and(val, order);
3430                }
3431            }
3432
3433            cfg_has_atomic_cas! {
3434            doc_comment! {
3435                concat!("Bitwise \"nand\" with the current value.
3436
3437Performs a bitwise \"nand\" operation on the current value and the argument `val`, and
3438sets the new value to the result.
3439
3440Returns the previous value.
3441
3442`fetch_nand` takes an [`Ordering`] argument which describes the memory ordering
3443of this operation. All ordering modes are possible. Note that using
3444[`Acquire`] makes the store part of this operation [`Relaxed`], and
3445using [`Release`] makes the load part [`Relaxed`].
3446
3447# Examples
3448
3449```
3450use portable_atomic::{", stringify!($atomic_type), ", Ordering};
3451
3452let foo = ", stringify!($atomic_type), "::new(0x13);
3453assert_eq!(foo.fetch_nand(0x31, Ordering::SeqCst), 0x13);
3454assert_eq!(foo.load(Ordering::SeqCst), !(0x13 & 0x31));
3455```"),
3456                #[inline]
3457                #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
3458                pub fn fetch_nand(&self, val: $int_type, order: Ordering) -> $int_type {
3459                    self.inner.fetch_nand(val, order)
3460                }
3461            }
3462            } // cfg_has_atomic_cas!
3463
3464            doc_comment! {
3465                concat!("Bitwise \"or\" with the current value.
3466
3467Performs a bitwise \"or\" operation on the current value and the argument `val`, and
3468sets the new value to the result.
3469
3470Returns the previous value.
3471
3472`fetch_or` takes an [`Ordering`] argument which describes the memory ordering
3473of this operation. All ordering modes are possible. Note that using
3474[`Acquire`] makes the store part of this operation [`Relaxed`], and
3475using [`Release`] makes the load part [`Relaxed`].
3476
3477# Examples
3478
3479```
3480use portable_atomic::{", stringify!($atomic_type), ", Ordering};
3481
3482let foo = ", stringify!($atomic_type), "::new(0b101101);
3483assert_eq!(foo.fetch_or(0b110011, Ordering::SeqCst), 0b101101);
3484assert_eq!(foo.load(Ordering::SeqCst), 0b111111);
3485```"),
3486                #[inline]
3487                #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
3488                pub fn fetch_or(&self, val: $int_type, order: Ordering) -> $int_type {
3489                    self.inner.fetch_or(val, order)
3490                }
3491            }
3492
3493            doc_comment! {
3494                concat!("Bitwise \"or\" with the current value.
3495
3496Performs a bitwise \"or\" operation on the current value and the argument `val`, and
3497sets the new value to the result.
3498
3499Unlike `fetch_or`, this does not return the previous value.
3500
3501`or` takes an [`Ordering`] argument which describes the memory ordering
3502of this operation. All ordering modes are possible. Note that using
3503[`Acquire`] makes the store part of this operation [`Relaxed`], and
3504using [`Release`] makes the load part [`Relaxed`].
3505
3506This function may generate more efficient code than `fetch_or` on some platforms.
3507
3508- x86/x86_64: `lock or` instead of `cmpxchg` loop ({8,16,32}-bit atomics on x86, but additionally 64-bit atomics on x86_64)
3509- MSP430: `or` instead of disabling interrupts ({8,16}-bit atomics)
3510
3511Note: On x86/x86_64, the use of either function should not usually
3512affect the generated code, because LLVM can properly optimize the case
3513where the result is unused.
3514
3515# Examples
3516
3517```
3518use portable_atomic::{", stringify!($atomic_type), ", Ordering};
3519
3520let foo = ", stringify!($atomic_type), "::new(0b101101);
3521assert_eq!(foo.fetch_or(0b110011, Ordering::SeqCst), 0b101101);
3522assert_eq!(foo.load(Ordering::SeqCst), 0b111111);
3523```"),
3524                #[inline]
3525                #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
3526                pub fn or(&self, val: $int_type, order: Ordering) {
3527                    self.inner.or(val, order);
3528                }
3529            }
3530
3531            doc_comment! {
3532                concat!("Bitwise \"xor\" with the current value.
3533
3534Performs a bitwise \"xor\" operation on the current value and the argument `val`, and
3535sets the new value to the result.
3536
3537Returns the previous value.
3538
3539`fetch_xor` takes an [`Ordering`] argument which describes the memory ordering
3540of this operation. All ordering modes are possible. Note that using
3541[`Acquire`] makes the store part of this operation [`Relaxed`], and
3542using [`Release`] makes the load part [`Relaxed`].
3543
3544# Examples
3545
3546```
3547use portable_atomic::{", stringify!($atomic_type), ", Ordering};
3548
3549let foo = ", stringify!($atomic_type), "::new(0b101101);
3550assert_eq!(foo.fetch_xor(0b110011, Ordering::SeqCst), 0b101101);
3551assert_eq!(foo.load(Ordering::SeqCst), 0b011110);
3552```"),
3553                #[inline]
3554                #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
3555                pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
3556                    self.inner.fetch_xor(val, order)
3557                }
3558            }
3559
3560            doc_comment! {
3561                concat!("Bitwise \"xor\" with the current value.
3562
3563Performs a bitwise \"xor\" operation on the current value and the argument `val`, and
3564sets the new value to the result.
3565
3566Unlike `fetch_xor`, this does not return the previous value.
3567
3568`xor` takes an [`Ordering`] argument which describes the memory ordering
3569of this operation. All ordering modes are possible. Note that using
3570[`Acquire`] makes the store part of this operation [`Relaxed`], and
3571using [`Release`] makes the load part [`Relaxed`].
3572
3573This function may generate more efficient code than `fetch_xor` on some platforms.
3574
3575- x86/x86_64: `lock xor` instead of `cmpxchg` loop ({8,16,32}-bit atomics on x86, but additionally 64-bit atomics on x86_64)
3576- MSP430: `xor` instead of disabling interrupts ({8,16}-bit atomics)
3577
3578Note: On x86/x86_64, the use of either function should not usually
3579affect the generated code, because LLVM can properly optimize the case
3580where the result is unused.
3581
3582# Examples
3583
3584```
3585use portable_atomic::{", stringify!($atomic_type), ", Ordering};
3586
3587let foo = ", stringify!($atomic_type), "::new(0b101101);
3588foo.xor(0b110011, Ordering::SeqCst);
3589assert_eq!(foo.load(Ordering::SeqCst), 0b011110);
3590```"),
3591                #[inline]
3592                #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
3593                pub fn xor(&self, val: $int_type, order: Ordering) {
3594                    self.inner.xor(val, order);
3595                }
3596            }
3597
3598            cfg_has_atomic_cas! {
3599            doc_comment! {
3600                concat!("Fetches the value, and applies a function to it that returns an optional
3601new value. Returns a `Result` of `Ok(previous_value)` if the function returned `Some(_)`, else
3602`Err(previous_value)`.
3603
3604Note: This may call the function multiple times if the value has been changed from other threads in
3605the meantime, as long as the function returns `Some(_)`, but the function will have been applied
3606only once to the stored value.
3607
3608`fetch_update` takes two [`Ordering`] arguments to describe the memory ordering of this operation.
3609The first describes the required ordering for when the operation finally succeeds while the second
3610describes the required ordering for loads. These correspond to the success and failure orderings of
3611[`compare_exchange`](Self::compare_exchange) respectively.
3612
3613Using [`Acquire`] as success ordering makes the store part
3614of this operation [`Relaxed`], and using [`Release`] makes the final successful load
3615[`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
3616
3617# Panics
3618
3619Panics if `fetch_order` is [`Release`], [`AcqRel`].
3620
3621# Considerations
3622
3623This method is not magic; it is not provided by the hardware.
3624It is implemented in terms of [`compare_exchange_weak`](Self::compare_exchange_weak),
3625and suffers from the same drawbacks.
3626In particular, this method will not circumvent the [ABA Problem].
3627
3628[ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
3629
3630# Examples
3631
3632```
3633use portable_atomic::{", stringify!($atomic_type), ", Ordering};
3634
3635let x = ", stringify!($atomic_type), "::new(7);
3636assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |_| None), Err(7));
3637assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(x + 1)), Ok(7));
3638assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(x + 1)), Ok(8));
3639assert_eq!(x.load(Ordering::SeqCst), 9);
3640```"),
3641                #[inline]
3642                #[cfg_attr(
3643                    any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri),
3644                    track_caller
3645                )]
3646                pub fn fetch_update<F>(
3647                    &self,
3648                    set_order: Ordering,
3649                    fetch_order: Ordering,
3650                    mut f: F,
3651                ) -> Result<$int_type, $int_type>
3652                where
3653                    F: FnMut($int_type) -> Option<$int_type>,
3654                {
3655                    let mut prev = self.load(fetch_order);
3656                    while let Some(next) = f(prev) {
3657                        match self.compare_exchange_weak(prev, next, set_order, fetch_order) {
3658                            x @ Ok(_) => return x,
3659                            Err(next_prev) => prev = next_prev,
3660                        }
3661                    }
3662                    Err(prev)
3663                }
3664            }
3665            } // cfg_has_atomic_cas!
3666
3667            $cfg_has_atomic_cas_or_amo32_or_8! {
3668            doc_comment! {
3669                concat!("Maximum with the current value.
3670
3671Finds the maximum of the current value and the argument `val`, and
3672sets the new value to the result.
3673
3674Returns the previous value.
3675
3676`fetch_max` takes an [`Ordering`] argument which describes the memory ordering
3677of this operation. All ordering modes are possible. Note that using
3678[`Acquire`] makes the store part of this operation [`Relaxed`], and
3679using [`Release`] makes the load part [`Relaxed`].
3680
3681# Examples
3682
3683```
3684use portable_atomic::{", stringify!($atomic_type), ", Ordering};
3685
3686let foo = ", stringify!($atomic_type), "::new(23);
3687assert_eq!(foo.fetch_max(42, Ordering::SeqCst), 23);
3688assert_eq!(foo.load(Ordering::SeqCst), 42);
3689```
3690
3691If you want to obtain the maximum value in one step, you can use the following:
3692
3693```
3694use portable_atomic::{", stringify!($atomic_type), ", Ordering};
3695
3696let foo = ", stringify!($atomic_type), "::new(23);
3697let bar = 42;
3698let max_foo = foo.fetch_max(bar, Ordering::SeqCst).max(bar);
3699assert!(max_foo == 42);
3700```"),
3701                #[inline]
3702                #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
3703                pub fn fetch_max(&self, val: $int_type, order: Ordering) -> $int_type {
3704                    self.inner.fetch_max(val, order)
3705                }
3706            }
3707
3708            doc_comment! {
3709                concat!("Minimum with the current value.
3710
3711Finds the minimum of the current value and the argument `val`, and
3712sets the new value to the result.
3713
3714Returns the previous value.
3715
3716`fetch_min` takes an [`Ordering`] argument which describes the memory ordering
3717of this operation. All ordering modes are possible. Note that using
3718[`Acquire`] makes the store part of this operation [`Relaxed`], and
3719using [`Release`] makes the load part [`Relaxed`].
3720
3721# Examples
3722
3723```
3724use portable_atomic::{", stringify!($atomic_type), ", Ordering};
3725
3726let foo = ", stringify!($atomic_type), "::new(23);
3727assert_eq!(foo.fetch_min(42, Ordering::Relaxed), 23);
3728assert_eq!(foo.load(Ordering::Relaxed), 23);
3729assert_eq!(foo.fetch_min(22, Ordering::Relaxed), 23);
3730assert_eq!(foo.load(Ordering::Relaxed), 22);
3731```
3732
3733If you want to obtain the minimum value in one step, you can use the following:
3734
3735```
3736use portable_atomic::{", stringify!($atomic_type), ", Ordering};
3737
3738let foo = ", stringify!($atomic_type), "::new(23);
3739let bar = 12;
3740let min_foo = foo.fetch_min(bar, Ordering::SeqCst).min(bar);
3741assert_eq!(min_foo, 12);
3742```"),
3743                #[inline]
3744                #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
3745                pub fn fetch_min(&self, val: $int_type, order: Ordering) -> $int_type {
3746                    self.inner.fetch_min(val, order)
3747                }
3748            }
3749            } // $cfg_has_atomic_cas_or_amo32_or_8!
3750
3751            doc_comment! {
3752                concat!("Sets the bit at the specified bit-position to 1.
3753
3754Returns `true` if the specified bit was previously set to 1.
3755
3756`bit_set` takes an [`Ordering`] argument which describes the memory ordering
3757of this operation. All ordering modes are possible. Note that using
3758[`Acquire`] makes the store part of this operation [`Relaxed`], and
3759using [`Release`] makes the load part [`Relaxed`].
3760
3761This corresponds to x86's `lock bts`, and the implementation calls them on x86/x86_64.
3762
3763# Examples
3764
3765```
3766use portable_atomic::{", stringify!($atomic_type), ", Ordering};
3767
3768let foo = ", stringify!($atomic_type), "::new(0b0000);
3769assert!(!foo.bit_set(0, Ordering::Relaxed));
3770assert_eq!(foo.load(Ordering::Relaxed), 0b0001);
3771assert!(foo.bit_set(0, Ordering::Relaxed));
3772assert_eq!(foo.load(Ordering::Relaxed), 0b0001);
3773```"),
3774                #[inline]
3775                #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
3776                pub fn bit_set(&self, bit: u32, order: Ordering) -> bool {
3777                    self.inner.bit_set(bit, order)
3778                }
3779            }
3780
3781            doc_comment! {
3782                concat!("Clears the bit at the specified bit-position to 0.
3783
3784Returns `true` if the specified bit was previously set to 1.
3785
3786`bit_clear` takes an [`Ordering`] argument which describes the memory ordering
3787of this operation. All ordering modes are possible. Note that using
3788[`Acquire`] makes the store part of this operation [`Relaxed`], and
3789using [`Release`] makes the load part [`Relaxed`].
3790
3791This corresponds to x86's `lock btr`, and the implementation calls them on x86/x86_64.
3792
3793# Examples
3794
3795```
3796use portable_atomic::{", stringify!($atomic_type), ", Ordering};
3797
3798let foo = ", stringify!($atomic_type), "::new(0b0001);
3799assert!(foo.bit_clear(0, Ordering::Relaxed));
3800assert_eq!(foo.load(Ordering::Relaxed), 0b0000);
3801```"),
3802                #[inline]
3803                #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
3804                pub fn bit_clear(&self, bit: u32, order: Ordering) -> bool {
3805                    self.inner.bit_clear(bit, order)
3806                }
3807            }
3808
3809            doc_comment! {
3810                concat!("Toggles the bit at the specified bit-position.
3811
3812Returns `true` if the specified bit was previously set to 1.
3813
3814`bit_toggle` takes an [`Ordering`] argument which describes the memory ordering
3815of this operation. All ordering modes are possible. Note that using
3816[`Acquire`] makes the store part of this operation [`Relaxed`], and
3817using [`Release`] makes the load part [`Relaxed`].
3818
3819This corresponds to x86's `lock btc`, and the implementation calls them on x86/x86_64.
3820
3821# Examples
3822
3823```
3824use portable_atomic::{", stringify!($atomic_type), ", Ordering};
3825
3826let foo = ", stringify!($atomic_type), "::new(0b0000);
3827assert!(!foo.bit_toggle(0, Ordering::Relaxed));
3828assert_eq!(foo.load(Ordering::Relaxed), 0b0001);
3829assert!(foo.bit_toggle(0, Ordering::Relaxed));
3830assert_eq!(foo.load(Ordering::Relaxed), 0b0000);
3831```"),
3832                #[inline]
3833                #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
3834                pub fn bit_toggle(&self, bit: u32, order: Ordering) -> bool {
3835                    self.inner.bit_toggle(bit, order)
3836                }
3837            }
3838
3839            doc_comment! {
3840                concat!("Logical negates the current value, and sets the new value to the result.
3841
3842Returns the previous value.
3843
3844`fetch_not` takes an [`Ordering`] argument which describes the memory ordering
3845of this operation. All ordering modes are possible. Note that using
3846[`Acquire`] makes the store part of this operation [`Relaxed`], and
3847using [`Release`] makes the load part [`Relaxed`].
3848
3849# Examples
3850
3851```
3852use portable_atomic::{", stringify!($atomic_type), ", Ordering};
3853
3854let foo = ", stringify!($atomic_type), "::new(0);
3855assert_eq!(foo.fetch_not(Ordering::Relaxed), 0);
3856assert_eq!(foo.load(Ordering::Relaxed), !0);
3857```"),
3858                #[inline]
3859                #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
3860                pub fn fetch_not(&self, order: Ordering) -> $int_type {
3861                    self.inner.fetch_not(order)
3862                }
3863            }
3864
3865            doc_comment! {
3866                concat!("Logical negates the current value, and sets the new value to the result.
3867
3868Unlike `fetch_not`, this does not return the previous value.
3869
3870`not` takes an [`Ordering`] argument which describes the memory ordering
3871of this operation. All ordering modes are possible. Note that using
3872[`Acquire`] makes the store part of this operation [`Relaxed`], and
3873using [`Release`] makes the load part [`Relaxed`].
3874
3875This function may generate more efficient code than `fetch_not` on some platforms.
3876
3877- x86/x86_64: `lock not` instead of `cmpxchg` loop ({8,16,32}-bit atomics on x86, but additionally 64-bit atomics on x86_64)
3878- MSP430: `inv` instead of disabling interrupts ({8,16}-bit atomics)
3879
3880# Examples
3881
3882```
3883use portable_atomic::{", stringify!($atomic_type), ", Ordering};
3884
3885let foo = ", stringify!($atomic_type), "::new(0);
3886foo.not(Ordering::Relaxed);
3887assert_eq!(foo.load(Ordering::Relaxed), !0);
3888```"),
3889                #[inline]
3890                #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
3891                pub fn not(&self, order: Ordering) {
3892                    self.inner.not(order);
3893                }
3894            }
3895
3896            cfg_has_atomic_cas! {
3897            doc_comment! {
3898                concat!("Negates the current value, and sets the new value to the result.
3899
3900Returns the previous value.
3901
3902`fetch_neg` takes an [`Ordering`] argument which describes the memory ordering
3903of this operation. All ordering modes are possible. Note that using
3904[`Acquire`] makes the store part of this operation [`Relaxed`], and
3905using [`Release`] makes the load part [`Relaxed`].
3906
3907# Examples
3908
3909```
3910use portable_atomic::{", stringify!($atomic_type), ", Ordering};
3911
3912let foo = ", stringify!($atomic_type), "::new(5);
3913assert_eq!(foo.fetch_neg(Ordering::Relaxed), 5);
3914assert_eq!(foo.load(Ordering::Relaxed), 5_", stringify!($int_type), ".wrapping_neg());
3915assert_eq!(foo.fetch_neg(Ordering::Relaxed), 5_", stringify!($int_type), ".wrapping_neg());
3916assert_eq!(foo.load(Ordering::Relaxed), 5);
3917```"),
3918                #[inline]
3919                #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
3920                pub fn fetch_neg(&self, order: Ordering) -> $int_type {
3921                    self.inner.fetch_neg(order)
3922                }
3923            }
3924
3925            doc_comment! {
3926                concat!("Negates the current value, and sets the new value to the result.
3927
3928Unlike `fetch_neg`, this does not return the previous value.
3929
3930`neg` takes an [`Ordering`] argument which describes the memory ordering
3931of this operation. All ordering modes are possible. Note that using
3932[`Acquire`] makes the store part of this operation [`Relaxed`], and
3933using [`Release`] makes the load part [`Relaxed`].
3934
3935This function may generate more efficient code than `fetch_neg` on some platforms.
3936
3937- x86/x86_64: `lock neg` instead of `cmpxchg` loop ({8,16,32}-bit atomics on x86, but additionally 64-bit atomics on x86_64)
3938
3939# Examples
3940
3941```
3942use portable_atomic::{", stringify!($atomic_type), ", Ordering};
3943
3944let foo = ", stringify!($atomic_type), "::new(5);
3945foo.neg(Ordering::Relaxed);
3946assert_eq!(foo.load(Ordering::Relaxed), 5_", stringify!($int_type), ".wrapping_neg());
3947foo.neg(Ordering::Relaxed);
3948assert_eq!(foo.load(Ordering::Relaxed), 5);
3949```"),
3950                #[inline]
3951                #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
3952                pub fn neg(&self, order: Ordering) {
3953                    self.inner.neg(order);
3954                }
3955            }
3956            } // cfg_has_atomic_cas!
3957            } // cfg_has_atomic_cas_or_amo32!
3958
3959            const_fn! {
3960                const_if: #[cfg(not(portable_atomic_no_const_raw_ptr_deref))];
3961                /// Returns a mutable pointer to the underlying integer.
3962                ///
3963                /// Returning an `*mut` pointer from a shared reference to this atomic is
3964                /// safe because the atomic types work with interior mutability. Any use of
3965                /// the returned raw pointer requires an `unsafe` block and has to uphold
3966                /// the safety requirements. If there is concurrent access, note the following
3967                /// additional safety requirements:
3968                ///
3969                /// - If this atomic type is [lock-free](Self::is_lock_free), any concurrent
3970                ///   operations on it must be atomic.
3971                /// - Otherwise, any concurrent operations on it must be compatible with
3972                ///   operations performed by this atomic type.
3973                ///
3974                /// This is `const fn` on Rust 1.58+.
3975                #[inline]
3976                pub const fn as_ptr(&self) -> *mut $int_type {
3977                    self.inner.as_ptr()
3978                }
3979            }
3980        }
3981        // See https://github.com/taiki-e/portable-atomic/issues/180
3982        #[cfg(not(feature = "require-cas"))]
3983        cfg_no_atomic_cas! {
3984        #[doc(hidden)]
3985        #[allow(unused_variables, clippy::unused_self, clippy::extra_unused_lifetimes)]
3986        impl<'a> $atomic_type {
3987            $cfg_no_atomic_cas_or_amo32_or_8! {
3988            #[inline]
3989            pub fn swap(&self, val: $int_type, order: Ordering) -> $int_type
3990            where
3991                &'a Self: HasSwap,
3992            {
3993                unimplemented!()
3994            }
3995            } // $cfg_no_atomic_cas_or_amo32_or_8!
3996            #[inline]
3997            pub fn compare_exchange(
3998                &self,
3999                current: $int_type,
4000                new: $int_type,
4001                success: Ordering,
4002                failure: Ordering,
4003            ) -> Result<$int_type, $int_type>
4004            where
4005                &'a Self: HasCompareExchange,
4006            {
4007                unimplemented!()
4008            }
4009            #[inline]
4010            pub fn compare_exchange_weak(
4011                &self,
4012                current: $int_type,
4013                new: $int_type,
4014                success: Ordering,
4015                failure: Ordering,
4016            ) -> Result<$int_type, $int_type>
4017            where
4018                &'a Self: HasCompareExchangeWeak,
4019            {
4020                unimplemented!()
4021            }
4022            $cfg_no_atomic_cas_or_amo32_or_8! {
4023            #[inline]
4024            pub fn fetch_add(&self, val: $int_type, order: Ordering) -> $int_type
4025            where
4026                &'a Self: HasFetchAdd,
4027            {
4028                unimplemented!()
4029            }
4030            #[inline]
4031            pub fn add(&self, val: $int_type, order: Ordering)
4032            where
4033                &'a Self: HasAdd,
4034            {
4035                unimplemented!()
4036            }
4037            #[inline]
4038            pub fn fetch_sub(&self, val: $int_type, order: Ordering) -> $int_type
4039            where
4040                &'a Self: HasFetchSub,
4041            {
4042                unimplemented!()
4043            }
4044            #[inline]
4045            pub fn sub(&self, val: $int_type, order: Ordering)
4046            where
4047                &'a Self: HasSub,
4048            {
4049                unimplemented!()
4050            }
4051            } // $cfg_no_atomic_cas_or_amo32_or_8!
4052            cfg_no_atomic_cas_or_amo32! {
4053            #[inline]
4054            pub fn fetch_and(&self, val: $int_type, order: Ordering) -> $int_type
4055            where
4056                &'a Self: HasFetchAnd,
4057            {
4058                unimplemented!()
4059            }
4060            #[inline]
4061            pub fn and(&self, val: $int_type, order: Ordering)
4062            where
4063                &'a Self: HasAnd,
4064            {
4065                unimplemented!()
4066            }
4067            } // cfg_no_atomic_cas_or_amo32!
4068            #[inline]
4069            pub fn fetch_nand(&self, val: $int_type, order: Ordering) -> $int_type
4070            where
4071                &'a Self: HasFetchNand,
4072            {
4073                unimplemented!()
4074            }
4075            cfg_no_atomic_cas_or_amo32! {
4076            #[inline]
4077            pub fn fetch_or(&self, val: $int_type, order: Ordering) -> $int_type
4078            where
4079                &'a Self: HasFetchOr,
4080            {
4081                unimplemented!()
4082            }
4083            #[inline]
4084            pub fn or(&self, val: $int_type, order: Ordering)
4085            where
4086                &'a Self: HasOr,
4087            {
4088                unimplemented!()
4089            }
4090            #[inline]
4091            pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type
4092            where
4093                &'a Self: HasFetchXor,
4094            {
4095                unimplemented!()
4096            }
4097            #[inline]
4098            pub fn xor(&self, val: $int_type, order: Ordering)
4099            where
4100                &'a Self: HasXor,
4101            {
4102                unimplemented!()
4103            }
4104            } // cfg_no_atomic_cas_or_amo32!
4105            #[inline]
4106            pub fn fetch_update<F>(
4107                &self,
4108                set_order: Ordering,
4109                fetch_order: Ordering,
4110                f: F,
4111            ) -> Result<$int_type, $int_type>
4112            where
4113                F: FnMut($int_type) -> Option<$int_type>,
4114                &'a Self: HasFetchUpdate,
4115            {
4116                unimplemented!()
4117            }
4118            $cfg_no_atomic_cas_or_amo32_or_8! {
4119            #[inline]
4120            pub fn fetch_max(&self, val: $int_type, order: Ordering) -> $int_type
4121            where
4122                &'a Self: HasFetchMax,
4123            {
4124                unimplemented!()
4125            }
4126            #[inline]
4127            pub fn fetch_min(&self, val: $int_type, order: Ordering) -> $int_type
4128            where
4129                &'a Self: HasFetchMin,
4130            {
4131                unimplemented!()
4132            }
4133            } // $cfg_no_atomic_cas_or_amo32_or_8!
4134            cfg_no_atomic_cas_or_amo32! {
4135            #[inline]
4136            pub fn bit_set(&self, bit: u32, order: Ordering) -> bool
4137            where
4138                &'a Self: HasBitSet,
4139            {
4140                unimplemented!()
4141            }
4142            #[inline]
4143            pub fn bit_clear(&self, bit: u32, order: Ordering) -> bool
4144            where
4145                &'a Self: HasBitClear,
4146            {
4147                unimplemented!()
4148            }
4149            #[inline]
4150            pub fn bit_toggle(&self, bit: u32, order: Ordering) -> bool
4151            where
4152                &'a Self: HasBitToggle,
4153            {
4154                unimplemented!()
4155            }
4156            #[inline]
4157            pub fn fetch_not(&self, order: Ordering) -> $int_type
4158            where
4159                &'a Self: HasFetchNot,
4160            {
4161                unimplemented!()
4162            }
4163            #[inline]
4164            pub fn not(&self, order: Ordering)
4165            where
4166                &'a Self: HasNot,
4167            {
4168                unimplemented!()
4169            }
4170            } // cfg_no_atomic_cas_or_amo32!
4171            #[inline]
4172            pub fn fetch_neg(&self, order: Ordering) -> $int_type
4173            where
4174                &'a Self: HasFetchNeg,
4175            {
4176                unimplemented!()
4177            }
4178            #[inline]
4179            pub fn neg(&self, order: Ordering)
4180            where
4181                &'a Self: HasNeg,
4182            {
4183                unimplemented!()
4184            }
4185        }
4186        } // cfg_no_atomic_cas!
4187        $(
4188            #[$cfg_float]
4189            atomic_int!(float,
4190                #[$cfg_float] $atomic_float_type, $float_type, $atomic_type, $int_type, $align
4191            );
4192        )?
4193    };
4194
4195    // AtomicF* impls
4196    (float,
4197        #[$cfg_float:meta]
4198        $atomic_type:ident,
4199        $float_type:ident,
4200        $atomic_int_type:ident,
4201        $int_type:ident,
4202        $align:literal
4203    ) => {
4204        doc_comment! {
4205            concat!("A floating point type which can be safely shared between threads.
4206
4207This type has the same in-memory representation as the underlying floating point type,
4208[`", stringify!($float_type), "`].
4209"
4210            ),
4211            #[cfg_attr(docsrs, doc($cfg_float))]
4212            // We can use #[repr(transparent)] here, but #[repr(C, align(N))]
4213            // will show clearer docs.
4214            #[repr(C, align($align))]
4215            pub struct $atomic_type {
4216                inner: imp::float::$atomic_type,
4217            }
4218        }
4219
4220        impl Default for $atomic_type {
4221            #[inline]
4222            fn default() -> Self {
4223                Self::new($float_type::default())
4224            }
4225        }
4226
4227        impl From<$float_type> for $atomic_type {
4228            #[inline]
4229            fn from(v: $float_type) -> Self {
4230                Self::new(v)
4231            }
4232        }
4233
4234        // UnwindSafe is implicitly implemented.
4235        #[cfg(not(portable_atomic_no_core_unwind_safe))]
4236        impl core::panic::RefUnwindSafe for $atomic_type {}
4237        #[cfg(all(portable_atomic_no_core_unwind_safe, feature = "std"))]
4238        impl std::panic::RefUnwindSafe for $atomic_type {}
4239
4240        impl_debug_and_serde!($atomic_type);
4241
4242        impl $atomic_type {
4243            /// Creates a new atomic float.
4244            #[inline]
4245            #[must_use]
4246            pub const fn new(v: $float_type) -> Self {
4247                static_assert_layout!($atomic_type, $float_type);
4248                Self { inner: imp::float::$atomic_type::new(v) }
4249            }
4250
4251            // TODO: update docs based on https://github.com/rust-lang/rust/pull/116762
4252            #[cfg(not(portable_atomic_no_const_raw_ptr_deref))]
4253            doc_comment! {
4254                concat!("Creates a new reference to an atomic float from a pointer.
4255
4256This is `const fn` on Rust 1.58+.
4257
4258# Safety
4259
4260* `ptr` must be aligned to `align_of::<", stringify!($atomic_type), ">()` (note that on some platforms this
4261  can be bigger than `align_of::<", stringify!($float_type), ">()`).
4262* `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`.
4263* If this atomic type is [lock-free](Self::is_lock_free), non-atomic accesses to the value
4264  behind `ptr` must have a happens-before relationship with atomic accesses via
4265  the returned value (or vice-versa).
4266  * In other words, time periods where the value is accessed atomically may not
4267    overlap with periods where the value is accessed non-atomically.
4268  * This requirement is trivially satisfied if `ptr` is never used non-atomically
4269    for the duration of lifetime `'a`. Most use cases should be able to follow
4270    this guideline.
4271  * This requirement is also trivially satisfied if all accesses (atomic or not) are
4272    done from the same thread.
4273* If this atomic type is *not* lock-free:
4274  * Any accesses to the value behind `ptr` must have a happens-before relationship
4275    with accesses via the returned value (or vice-versa).
4276  * Any concurrent accesses to the value behind `ptr` for the duration of lifetime `'a` must
4277    be compatible with operations performed by this atomic type.
4278* This method must not be used to create overlapping or mixed-size atomic
4279  accesses, as these are not supported by the memory model.
4280
4281[valid]: core::ptr#safety"),
4282                #[inline]
4283                #[must_use]
4284                pub const unsafe fn from_ptr<'a>(ptr: *mut $float_type) -> &'a Self {
4285                    #[allow(clippy::cast_ptr_alignment)]
4286                    // SAFETY: guaranteed by the caller
4287                    unsafe { &*(ptr as *mut Self as *const Self) }
4288                }
4289            }
4290            #[cfg(portable_atomic_no_const_raw_ptr_deref)]
4291            doc_comment! {
4292                concat!("Creates a new reference to an atomic float from a pointer.
4293
4294This is `const fn` on Rust 1.58+.
4295
4296# Safety
4297
4298* `ptr` must be aligned to `align_of::<", stringify!($atomic_type), ">()` (note that on some platforms this
4299  can be bigger than `align_of::<", stringify!($float_type), ">()`).
4300* `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`.
4301* If this atomic type is [lock-free](Self::is_lock_free), non-atomic accesses to the value
4302  behind `ptr` must have a happens-before relationship with atomic accesses via
4303  the returned value (or vice-versa).
4304  * In other words, time periods where the value is accessed atomically may not
4305    overlap with periods where the value is accessed non-atomically.
4306  * This requirement is trivially satisfied if `ptr` is never used non-atomically
4307    for the duration of lifetime `'a`. Most use cases should be able to follow
4308    this guideline.
4309  * This requirement is also trivially satisfied if all accesses (atomic or not) are
4310    done from the same thread.
4311* If this atomic type is *not* lock-free:
4312  * Any accesses to the value behind `ptr` must have a happens-before relationship
4313    with accesses via the returned value (or vice-versa).
4314  * Any concurrent accesses to the value behind `ptr` for the duration of lifetime `'a` must
4315    be compatible with operations performed by this atomic type.
4316* This method must not be used to create overlapping or mixed-size atomic
4317  accesses, as these are not supported by the memory model.
4318
4319[valid]: core::ptr#safety"),
4320                #[inline]
4321                #[must_use]
4322                pub unsafe fn from_ptr<'a>(ptr: *mut $float_type) -> &'a Self {
4323                    #[allow(clippy::cast_ptr_alignment)]
4324                    // SAFETY: guaranteed by the caller
4325                    unsafe { &*(ptr as *mut Self as *const Self) }
4326                }
4327            }
4328
4329            /// Returns `true` if operations on values of this type are lock-free.
4330            ///
4331            /// If the compiler or the platform doesn't support the necessary
4332            /// atomic instructions, global locks for every potentially
4333            /// concurrent atomic operation will be used.
4334            ///
4335            /// This function is guaranteed to always return the same result.
4336            #[inline]
4337            #[must_use]
4338            pub fn is_lock_free() -> bool {
4339                <imp::float::$atomic_type>::is_lock_free()
4340            }
4341
4342            /// Returns `true` if operations on values of this type are lock-free.
4343            ///
4344            /// If the compiler or the platform doesn't support the necessary
4345            /// atomic instructions, global locks for every potentially
4346            /// concurrent atomic operation will be used.
4347            ///
4348            /// **Note:** If the atomic operation relies on dynamic CPU feature detection,
4349            /// this type may be lock-free even if the function returns false.
4350            #[inline]
4351            #[must_use]
4352            pub const fn is_always_lock_free() -> bool {
4353                <imp::float::$atomic_type>::IS_ALWAYS_LOCK_FREE
4354            }
4355            #[cfg(test)]
4356            #[cfg_attr(all(not(debug_assertions), target_arch = "x86", not(target_feature = "sse2")), allow(dead_code))]
4357            const IS_ALWAYS_LOCK_FREE: bool = Self::is_always_lock_free();
4358
4359            const_fn! {
4360                const_if: #[cfg(not(portable_atomic_no_const_mut_refs))];
4361                /// Returns a mutable reference to the underlying float.
4362                ///
4363                /// This is safe because the mutable reference guarantees that no other threads are
4364                /// concurrently accessing the atomic data.
4365                ///
4366                /// This is `const fn` on Rust 1.83+.
4367                #[inline]
4368                pub const fn get_mut(&mut self) -> &mut $float_type {
4369                    // SAFETY: the mutable reference guarantees unique ownership.
4370                    unsafe { &mut *self.as_ptr() }
4371                }
4372            }
4373
4374            // TODO: Add from_mut/get_mut_slice/from_mut_slice once it is stable on std atomic types.
4375            // https://github.com/rust-lang/rust/issues/76314
4376
4377            const_fn! {
4378                const_if: #[cfg(not(portable_atomic_no_const_transmute))];
4379                /// Consumes the atomic and returns the contained value.
4380                ///
4381                /// This is safe because passing `self` by value guarantees that no other threads are
4382                /// concurrently accessing the atomic data.
4383                ///
4384                /// This is `const fn` on Rust 1.56+.
4385                #[inline]
4386                pub const fn into_inner(self) -> $float_type {
4387                    // SAFETY: $atomic_type and $float_type have the same size and in-memory representations,
4388                    // so they can be safely transmuted.
4389                    // (const UnsafeCell::into_inner is unstable)
4390                    unsafe { core::mem::transmute(self) }
4391                }
4392            }
4393
4394            /// Loads a value from the atomic float.
4395            ///
4396            /// `load` takes an [`Ordering`] argument which describes the memory ordering of this operation.
4397            /// Possible values are [`SeqCst`], [`Acquire`] and [`Relaxed`].
4398            ///
4399            /// # Panics
4400            ///
4401            /// Panics if `order` is [`Release`] or [`AcqRel`].
4402            #[inline]
4403            #[cfg_attr(
4404                any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri),
4405                track_caller
4406            )]
4407            pub fn load(&self, order: Ordering) -> $float_type {
4408                self.inner.load(order)
4409            }
4410
4411            /// Stores a value into the atomic float.
4412            ///
4413            /// `store` takes an [`Ordering`] argument which describes the memory ordering of this operation.
4414            ///  Possible values are [`SeqCst`], [`Release`] and [`Relaxed`].
4415            ///
4416            /// # Panics
4417            ///
4418            /// Panics if `order` is [`Acquire`] or [`AcqRel`].
4419            #[inline]
4420            #[cfg_attr(
4421                any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri),
4422                track_caller
4423            )]
4424            pub fn store(&self, val: $float_type, order: Ordering) {
4425                self.inner.store(val, order)
4426            }
4427
4428            cfg_has_atomic_cas_or_amo32! {
4429            /// Stores a value into the atomic float, returning the previous value.
4430            ///
4431            /// `swap` takes an [`Ordering`] argument which describes the memory ordering
4432            /// of this operation. All ordering modes are possible. Note that using
4433            /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
4434            /// using [`Release`] makes the load part [`Relaxed`].
4435            #[inline]
4436            #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
4437            pub fn swap(&self, val: $float_type, order: Ordering) -> $float_type {
4438                self.inner.swap(val, order)
4439            }
4440
4441            cfg_has_atomic_cas! {
4442            /// Stores a value into the atomic float if the current value is the same as
4443            /// the `current` value.
4444            ///
4445            /// The return value is a result indicating whether the new value was written and
4446            /// containing the previous value. On success this value is guaranteed to be equal to
4447            /// `current`.
4448            ///
4449            /// `compare_exchange` takes two [`Ordering`] arguments to describe the memory
4450            /// ordering of this operation. `success` describes the required ordering for the
4451            /// read-modify-write operation that takes place if the comparison with `current` succeeds.
4452            /// `failure` describes the required ordering for the load operation that takes place when
4453            /// the comparison fails. Using [`Acquire`] as success ordering makes the store part
4454            /// of this operation [`Relaxed`], and using [`Release`] makes the successful load
4455            /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
4456            ///
4457            /// # Panics
4458            ///
4459            /// Panics if `failure` is [`Release`], [`AcqRel`].
4460            #[cfg_attr(docsrs, doc(alias = "compare_and_swap"))]
4461            #[inline]
4462            #[cfg_attr(
4463                any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri),
4464                track_caller
4465            )]
4466            pub fn compare_exchange(
4467                &self,
4468                current: $float_type,
4469                new: $float_type,
4470                success: Ordering,
4471                failure: Ordering,
4472            ) -> Result<$float_type, $float_type> {
4473                self.inner.compare_exchange(current, new, success, failure)
4474            }
4475
4476            /// Stores a value into the atomic float if the current value is the same as
4477            /// the `current` value.
4478            /// Unlike [`compare_exchange`](Self::compare_exchange)
4479            /// this function is allowed to spuriously fail even
4480            /// when the comparison succeeds, which can result in more efficient code on some
4481            /// platforms. The return value is a result indicating whether the new value was
4482            /// written and containing the previous value.
4483            ///
4484            /// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory
4485            /// ordering of this operation. `success` describes the required ordering for the
4486            /// read-modify-write operation that takes place if the comparison with `current` succeeds.
4487            /// `failure` describes the required ordering for the load operation that takes place when
4488            /// the comparison fails. Using [`Acquire`] as success ordering makes the store part
4489            /// of this operation [`Relaxed`], and using [`Release`] makes the successful load
4490            /// [`Relaxed`]. The failure ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
4491            ///
4492            /// # Panics
4493            ///
4494            /// Panics if `failure` is [`Release`], [`AcqRel`].
4495            #[cfg_attr(docsrs, doc(alias = "compare_and_swap"))]
4496            #[inline]
4497            #[cfg_attr(
4498                any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri),
4499                track_caller
4500            )]
4501            pub fn compare_exchange_weak(
4502                &self,
4503                current: $float_type,
4504                new: $float_type,
4505                success: Ordering,
4506                failure: Ordering,
4507            ) -> Result<$float_type, $float_type> {
4508                self.inner.compare_exchange_weak(current, new, success, failure)
4509            }
4510
4511            /// Adds to the current value, returning the previous value.
4512            ///
4513            /// `fetch_add` takes an [`Ordering`] argument which describes the memory ordering
4514            /// of this operation. All ordering modes are possible. Note that using
4515            /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
4516            /// using [`Release`] makes the load part [`Relaxed`].
4517            #[inline]
4518            #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
4519            pub fn fetch_add(&self, val: $float_type, order: Ordering) -> $float_type {
4520                self.inner.fetch_add(val, order)
4521            }
4522
4523            /// Subtracts from the current value, returning the previous value.
4524            ///
4525            /// `fetch_sub` takes an [`Ordering`] argument which describes the memory ordering
4526            /// of this operation. All ordering modes are possible. Note that using
4527            /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
4528            /// using [`Release`] makes the load part [`Relaxed`].
4529            #[inline]
4530            #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
4531            pub fn fetch_sub(&self, val: $float_type, order: Ordering) -> $float_type {
4532                self.inner.fetch_sub(val, order)
4533            }
4534
4535            /// Fetches the value, and applies a function to it that returns an optional
4536            /// new value. Returns a `Result` of `Ok(previous_value)` if the function returned `Some(_)`, else
4537            /// `Err(previous_value)`.
4538            ///
4539            /// Note: This may call the function multiple times if the value has been changed from other threads in
4540            /// the meantime, as long as the function returns `Some(_)`, but the function will have been applied
4541            /// only once to the stored value.
4542            ///
4543            /// `fetch_update` takes two [`Ordering`] arguments to describe the memory ordering of this operation.
4544            /// The first describes the required ordering for when the operation finally succeeds while the second
4545            /// describes the required ordering for loads. These correspond to the success and failure orderings of
4546            /// [`compare_exchange`](Self::compare_exchange) respectively.
4547            ///
4548            /// Using [`Acquire`] as success ordering makes the store part
4549            /// of this operation [`Relaxed`], and using [`Release`] makes the final successful load
4550            /// [`Relaxed`]. The (failed) load ordering can only be [`SeqCst`], [`Acquire`] or [`Relaxed`].
4551            ///
4552            /// # Panics
4553            ///
4554            /// Panics if `fetch_order` is [`Release`], [`AcqRel`].
4555            ///
4556            /// # Considerations
4557            ///
4558            /// This method is not magic; it is not provided by the hardware.
4559            /// It is implemented in terms of [`compare_exchange_weak`](Self::compare_exchange_weak),
4560            /// and suffers from the same drawbacks.
4561            /// In particular, this method will not circumvent the [ABA Problem].
4562            ///
4563            /// [ABA Problem]: https://en.wikipedia.org/wiki/ABA_problem
4564            #[inline]
4565            #[cfg_attr(
4566                any(all(debug_assertions, not(portable_atomic_no_track_caller)), miri),
4567                track_caller
4568            )]
4569            pub fn fetch_update<F>(
4570                &self,
4571                set_order: Ordering,
4572                fetch_order: Ordering,
4573                mut f: F,
4574            ) -> Result<$float_type, $float_type>
4575            where
4576                F: FnMut($float_type) -> Option<$float_type>,
4577            {
4578                let mut prev = self.load(fetch_order);
4579                while let Some(next) = f(prev) {
4580                    match self.compare_exchange_weak(prev, next, set_order, fetch_order) {
4581                        x @ Ok(_) => return x,
4582                        Err(next_prev) => prev = next_prev,
4583                    }
4584                }
4585                Err(prev)
4586            }
4587
4588            /// Maximum with the current value.
4589            ///
4590            /// Finds the maximum of the current value and the argument `val`, and
4591            /// sets the new value to the result.
4592            ///
4593            /// Returns the previous value.
4594            ///
4595            /// `fetch_max` takes an [`Ordering`] argument which describes the memory ordering
4596            /// of this operation. All ordering modes are possible. Note that using
4597            /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
4598            /// using [`Release`] makes the load part [`Relaxed`].
4599            #[inline]
4600            #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
4601            pub fn fetch_max(&self, val: $float_type, order: Ordering) -> $float_type {
4602                self.inner.fetch_max(val, order)
4603            }
4604
4605            /// Minimum with the current value.
4606            ///
4607            /// Finds the minimum of the current value and the argument `val`, and
4608            /// sets the new value to the result.
4609            ///
4610            /// Returns the previous value.
4611            ///
4612            /// `fetch_min` takes an [`Ordering`] argument which describes the memory ordering
4613            /// of this operation. All ordering modes are possible. Note that using
4614            /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
4615            /// using [`Release`] makes the load part [`Relaxed`].
4616            #[inline]
4617            #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
4618            pub fn fetch_min(&self, val: $float_type, order: Ordering) -> $float_type {
4619                self.inner.fetch_min(val, order)
4620            }
4621            } // cfg_has_atomic_cas!
4622
4623            /// Negates the current value, and sets the new value to the result.
4624            ///
4625            /// Returns the previous value.
4626            ///
4627            /// `fetch_neg` takes an [`Ordering`] argument which describes the memory ordering
4628            /// of this operation. All ordering modes are possible. Note that using
4629            /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
4630            /// using [`Release`] makes the load part [`Relaxed`].
4631            #[inline]
4632            #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
4633            pub fn fetch_neg(&self, order: Ordering) -> $float_type {
4634                self.inner.fetch_neg(order)
4635            }
4636
4637            /// Computes the absolute value of the current value, and sets the
4638            /// new value to the result.
4639            ///
4640            /// Returns the previous value.
4641            ///
4642            /// `fetch_abs` takes an [`Ordering`] argument which describes the memory ordering
4643            /// of this operation. All ordering modes are possible. Note that using
4644            /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
4645            /// using [`Release`] makes the load part [`Relaxed`].
4646            #[inline]
4647            #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
4648            pub fn fetch_abs(&self, order: Ordering) -> $float_type {
4649                self.inner.fetch_abs(order)
4650            }
4651            } // cfg_has_atomic_cas_or_amo32!
4652
4653            #[cfg(not(portable_atomic_no_const_raw_ptr_deref))]
4654            doc_comment! {
4655                concat!("Raw transmutation to `&", stringify!($atomic_int_type), "`.
4656
4657See [`", stringify!($float_type) ,"::from_bits`] for some discussion of the
4658portability of this operation (there are almost no issues).
4659
4660This is `const fn` on Rust 1.58+."),
4661                #[inline]
4662                pub const fn as_bits(&self) -> &$atomic_int_type {
4663                    self.inner.as_bits()
4664                }
4665            }
4666            #[cfg(portable_atomic_no_const_raw_ptr_deref)]
4667            doc_comment! {
4668                concat!("Raw transmutation to `&", stringify!($atomic_int_type), "`.
4669
4670See [`", stringify!($float_type) ,"::from_bits`] for some discussion of the
4671portability of this operation (there are almost no issues).
4672
4673This is `const fn` on Rust 1.58+."),
4674                #[inline]
4675                pub fn as_bits(&self) -> &$atomic_int_type {
4676                    self.inner.as_bits()
4677                }
4678            }
4679
4680            const_fn! {
4681                const_if: #[cfg(not(portable_atomic_no_const_raw_ptr_deref))];
4682                /// Returns a mutable pointer to the underlying float.
4683                ///
4684                /// Returning an `*mut` pointer from a shared reference to this atomic is
4685                /// safe because the atomic types work with interior mutability. Any use of
4686                /// the returned raw pointer requires an `unsafe` block and has to uphold
4687                /// the safety requirements. If there is concurrent access, note the following
4688                /// additional safety requirements:
4689                ///
4690                /// - If this atomic type is [lock-free](Self::is_lock_free), any concurrent
4691                ///   operations on it must be atomic.
4692                /// - Otherwise, any concurrent operations on it must be compatible with
4693                ///   operations performed by this atomic type.
4694                ///
4695                /// This is `const fn` on Rust 1.58+.
4696                #[inline]
4697                pub const fn as_ptr(&self) -> *mut $float_type {
4698                    self.inner.as_ptr()
4699                }
4700            }
4701        }
4702        // See https://github.com/taiki-e/portable-atomic/issues/180
4703        #[cfg(not(feature = "require-cas"))]
4704        cfg_no_atomic_cas! {
4705        #[doc(hidden)]
4706        #[allow(unused_variables, clippy::unused_self, clippy::extra_unused_lifetimes)]
4707        impl<'a> $atomic_type {
4708            cfg_no_atomic_cas_or_amo32! {
4709            #[inline]
4710            pub fn swap(&self, val: $float_type, order: Ordering) -> $float_type
4711            where
4712                &'a Self: HasSwap,
4713            {
4714                unimplemented!()
4715            }
4716            } // cfg_no_atomic_cas_or_amo32!
4717            #[inline]
4718            pub fn compare_exchange(
4719                &self,
4720                current: $float_type,
4721                new: $float_type,
4722                success: Ordering,
4723                failure: Ordering,
4724            ) -> Result<$float_type, $float_type>
4725            where
4726                &'a Self: HasCompareExchange,
4727            {
4728                unimplemented!()
4729            }
4730            #[inline]
4731            pub fn compare_exchange_weak(
4732                &self,
4733                current: $float_type,
4734                new: $float_type,
4735                success: Ordering,
4736                failure: Ordering,
4737            ) -> Result<$float_type, $float_type>
4738            where
4739                &'a Self: HasCompareExchangeWeak,
4740            {
4741                unimplemented!()
4742            }
4743            #[inline]
4744            pub fn fetch_add(&self, val: $float_type, order: Ordering) -> $float_type
4745            where
4746                &'a Self: HasFetchAdd,
4747            {
4748                unimplemented!()
4749            }
4750            #[inline]
4751            pub fn fetch_sub(&self, val: $float_type, order: Ordering) -> $float_type
4752            where
4753                &'a Self: HasFetchSub,
4754            {
4755                unimplemented!()
4756            }
4757            #[inline]
4758            pub fn fetch_update<F>(
4759                &self,
4760                set_order: Ordering,
4761                fetch_order: Ordering,
4762                f: F,
4763            ) -> Result<$float_type, $float_type>
4764            where
4765                F: FnMut($float_type) -> Option<$float_type>,
4766                &'a Self: HasFetchUpdate,
4767            {
4768                unimplemented!()
4769            }
4770            #[inline]
4771            pub fn fetch_max(&self, val: $float_type, order: Ordering) -> $float_type
4772            where
4773                &'a Self: HasFetchMax,
4774            {
4775                unimplemented!()
4776            }
4777            #[inline]
4778            pub fn fetch_min(&self, val: $float_type, order: Ordering) -> $float_type
4779            where
4780                &'a Self: HasFetchMin,
4781            {
4782                unimplemented!()
4783            }
4784            cfg_no_atomic_cas_or_amo32! {
4785            #[inline]
4786            pub fn fetch_neg(&self, order: Ordering) -> $float_type
4787            where
4788                &'a Self: HasFetchNeg,
4789            {
4790                unimplemented!()
4791            }
4792            #[inline]
4793            pub fn fetch_abs(&self, order: Ordering) -> $float_type
4794            where
4795                &'a Self: HasFetchAbs,
4796            {
4797                unimplemented!()
4798            }
4799            } // cfg_no_atomic_cas_or_amo32!
4800        }
4801        } // cfg_no_atomic_cas!
4802    };
4803}
4804
4805cfg_has_atomic_ptr! {
4806    #[cfg(target_pointer_width = "16")]
4807    atomic_int!(AtomicIsize, isize, 2, cfg_has_atomic_cas_or_amo8, cfg_no_atomic_cas_or_amo8);
4808    #[cfg(target_pointer_width = "16")]
4809    atomic_int!(AtomicUsize, usize, 2, cfg_has_atomic_cas_or_amo8, cfg_no_atomic_cas_or_amo8);
4810    #[cfg(target_pointer_width = "32")]
4811    atomic_int!(AtomicIsize, isize, 4, cfg_has_atomic_cas_or_amo32, cfg_no_atomic_cas_or_amo32);
4812    #[cfg(target_pointer_width = "32")]
4813    atomic_int!(AtomicUsize, usize, 4, cfg_has_atomic_cas_or_amo32, cfg_no_atomic_cas_or_amo32);
4814    #[cfg(target_pointer_width = "64")]
4815    atomic_int!(AtomicIsize, isize, 8, cfg_has_atomic_cas_or_amo32, cfg_no_atomic_cas_or_amo32);
4816    #[cfg(target_pointer_width = "64")]
4817    atomic_int!(AtomicUsize, usize, 8, cfg_has_atomic_cas_or_amo32, cfg_no_atomic_cas_or_amo32);
4818    #[cfg(target_pointer_width = "128")]
4819    atomic_int!(AtomicIsize, isize, 16, cfg_has_atomic_cas_or_amo32, cfg_no_atomic_cas_or_amo32);
4820    #[cfg(target_pointer_width = "128")]
4821    atomic_int!(AtomicUsize, usize, 16, cfg_has_atomic_cas_or_amo32, cfg_no_atomic_cas_or_amo32);
4822}
4823
4824cfg_has_atomic_8! {
4825    atomic_int!(AtomicI8, i8, 1, cfg_has_atomic_cas_or_amo8, cfg_no_atomic_cas_or_amo8);
4826    atomic_int!(AtomicU8, u8, 1, cfg_has_atomic_cas_or_amo8, cfg_no_atomic_cas_or_amo8);
4827}
4828cfg_has_atomic_16! {
4829    atomic_int!(AtomicI16, i16, 2, cfg_has_atomic_cas_or_amo8, cfg_no_atomic_cas_or_amo8);
4830    atomic_int!(AtomicU16, u16, 2, cfg_has_atomic_cas_or_amo8, cfg_no_atomic_cas_or_amo8,
4831        #[cfg(all(feature = "float", portable_atomic_unstable_f16))] AtomicF16, f16);
4832}
4833cfg_has_atomic_32! {
4834    atomic_int!(AtomicI32, i32, 4, cfg_has_atomic_cas_or_amo32, cfg_no_atomic_cas_or_amo32);
4835    atomic_int!(AtomicU32, u32, 4, cfg_has_atomic_cas_or_amo32, cfg_no_atomic_cas_or_amo32,
4836        #[cfg(feature = "float")] AtomicF32, f32);
4837}
4838cfg_has_atomic_64! {
4839    atomic_int!(AtomicI64, i64, 8, cfg_has_atomic_cas_or_amo32, cfg_no_atomic_cas_or_amo32);
4840    atomic_int!(AtomicU64, u64, 8, cfg_has_atomic_cas_or_amo32, cfg_no_atomic_cas_or_amo32,
4841        #[cfg(feature = "float")] AtomicF64, f64);
4842}
4843cfg_has_atomic_128! {
4844    atomic_int!(AtomicI128, i128, 16, cfg_has_atomic_cas_or_amo32, cfg_no_atomic_cas_or_amo32);
4845    atomic_int!(AtomicU128, u128, 16, cfg_has_atomic_cas_or_amo32, cfg_no_atomic_cas_or_amo32,
4846        #[cfg(all(feature = "float", portable_atomic_unstable_f128))] AtomicF128, f128);
4847}
4848
4849// See https://github.com/taiki-e/portable-atomic/issues/180
4850#[cfg(not(feature = "require-cas"))]
4851cfg_no_atomic_cas! {
4852cfg_no_atomic_cas_or_amo32! {
4853#[cfg(feature = "float")]
4854use self::diagnostic_helper::HasFetchAbs;
4855use self::diagnostic_helper::{
4856    HasAnd, HasBitClear, HasBitSet, HasBitToggle, HasFetchAnd, HasFetchByteAdd, HasFetchByteSub,
4857    HasFetchNot, HasFetchOr, HasFetchPtrAdd, HasFetchPtrSub, HasFetchXor, HasNot, HasOr, HasXor,
4858};
4859} // cfg_no_atomic_cas_or_amo32!
4860cfg_no_atomic_cas_or_amo8! {
4861use self::diagnostic_helper::{HasAdd, HasSub, HasSwap};
4862} // cfg_no_atomic_cas_or_amo8!
4863#[cfg_attr(not(feature = "float"), allow(unused_imports))]
4864use self::diagnostic_helper::{
4865    HasCompareExchange, HasCompareExchangeWeak, HasFetchAdd, HasFetchMax, HasFetchMin,
4866    HasFetchNand, HasFetchNeg, HasFetchSub, HasFetchUpdate, HasNeg,
4867};
4868#[cfg_attr(
4869    any(
4870        all(
4871            portable_atomic_no_atomic_load_store,
4872            not(any(
4873                target_arch = "avr",
4874                target_arch = "bpf",
4875                target_arch = "msp430",
4876                target_arch = "riscv32",
4877                target_arch = "riscv64",
4878                feature = "critical-section",
4879                portable_atomic_unsafe_assume_single_core,
4880            )),
4881        ),
4882        not(feature = "float"),
4883    ),
4884    allow(dead_code, unreachable_pub)
4885)]
4886#[allow(unknown_lints, unnameable_types)] // Not public API. unnameable_types is available on Rust 1.79+
4887mod diagnostic_helper {
4888    cfg_no_atomic_cas_or_amo8! {
4889    #[doc(hidden)]
4890    #[cfg_attr(
4891        not(portable_atomic_no_diagnostic_namespace),
4892        diagnostic::on_unimplemented(
4893            message = "`swap` requires atomic CAS but not available on this target by default",
4894            label = "this associated function is not available on this target by default",
4895            note = "consider enabling one of the `critical-section` feature or `unsafe-assume-single-core` feature (or `portable_atomic_unsafe_assume_single_core` cfg)",
4896            note = "see <https://docs.rs/portable-atomic/latest/portable_atomic/#optional-features> for more."
4897        )
4898    )]
4899    pub trait HasSwap {}
4900    } // cfg_no_atomic_cas_or_amo8!
4901    #[doc(hidden)]
4902    #[cfg_attr(
4903        not(portable_atomic_no_diagnostic_namespace),
4904        diagnostic::on_unimplemented(
4905            message = "`compare_exchange` requires atomic CAS but not available on this target by default",
4906            label = "this associated function is not available on this target by default",
4907            note = "consider enabling one of the `critical-section` feature or `unsafe-assume-single-core` feature (or `portable_atomic_unsafe_assume_single_core` cfg)",
4908            note = "see <https://docs.rs/portable-atomic/latest/portable_atomic/#optional-features> for more."
4909        )
4910    )]
4911    pub trait HasCompareExchange {}
4912    #[doc(hidden)]
4913    #[cfg_attr(
4914        not(portable_atomic_no_diagnostic_namespace),
4915        diagnostic::on_unimplemented(
4916            message = "`compare_exchange_weak` requires atomic CAS but not available on this target by default",
4917            label = "this associated function is not available on this target by default",
4918            note = "consider enabling one of the `critical-section` feature or `unsafe-assume-single-core` feature (or `portable_atomic_unsafe_assume_single_core` cfg)",
4919            note = "see <https://docs.rs/portable-atomic/latest/portable_atomic/#optional-features> for more."
4920        )
4921    )]
4922    pub trait HasCompareExchangeWeak {}
4923    #[doc(hidden)]
4924    #[cfg_attr(
4925        not(portable_atomic_no_diagnostic_namespace),
4926        diagnostic::on_unimplemented(
4927            message = "`fetch_add` requires atomic CAS but not available on this target by default",
4928            label = "this associated function is not available on this target by default",
4929            note = "consider enabling one of the `critical-section` feature or `unsafe-assume-single-core` feature (or `portable_atomic_unsafe_assume_single_core` cfg)",
4930            note = "see <https://docs.rs/portable-atomic/latest/portable_atomic/#optional-features> for more."
4931        )
4932    )]
4933    pub trait HasFetchAdd {}
4934    cfg_no_atomic_cas_or_amo8! {
4935    #[doc(hidden)]
4936    #[cfg_attr(
4937        not(portable_atomic_no_diagnostic_namespace),
4938        diagnostic::on_unimplemented(
4939            message = "`add` requires atomic CAS but not available on this target by default",
4940            label = "this associated function is not available on this target by default",
4941            note = "consider enabling one of the `critical-section` feature or `unsafe-assume-single-core` feature (or `portable_atomic_unsafe_assume_single_core` cfg)",
4942            note = "see <https://docs.rs/portable-atomic/latest/portable_atomic/#optional-features> for more."
4943        )
4944    )]
4945    pub trait HasAdd {}
4946    } // cfg_no_atomic_cas_or_amo8!
4947    #[doc(hidden)]
4948    #[cfg_attr(
4949        not(portable_atomic_no_diagnostic_namespace),
4950        diagnostic::on_unimplemented(
4951            message = "`fetch_sub` requires atomic CAS but not available on this target by default",
4952            label = "this associated function is not available on this target by default",
4953            note = "consider enabling one of the `critical-section` feature or `unsafe-assume-single-core` feature (or `portable_atomic_unsafe_assume_single_core` cfg)",
4954            note = "see <https://docs.rs/portable-atomic/latest/portable_atomic/#optional-features> for more."
4955        )
4956    )]
4957    pub trait HasFetchSub {}
4958    cfg_no_atomic_cas_or_amo8! {
4959    #[doc(hidden)]
4960    #[cfg_attr(
4961        not(portable_atomic_no_diagnostic_namespace),
4962        diagnostic::on_unimplemented(
4963            message = "`sub` requires atomic CAS but not available on this target by default",
4964            label = "this associated function is not available on this target by default",
4965            note = "consider enabling one of the `critical-section` feature or `unsafe-assume-single-core` feature (or `portable_atomic_unsafe_assume_single_core` cfg)",
4966            note = "see <https://docs.rs/portable-atomic/latest/portable_atomic/#optional-features> for more."
4967        )
4968    )]
4969    pub trait HasSub {}
4970    } // cfg_no_atomic_cas_or_amo8!
4971    cfg_no_atomic_cas_or_amo32! {
4972    #[doc(hidden)]
4973    #[cfg_attr(
4974        not(portable_atomic_no_diagnostic_namespace),
4975        diagnostic::on_unimplemented(
4976            message = "`fetch_ptr_add` requires atomic CAS but not available on this target by default",
4977            label = "this associated function is not available on this target by default",
4978            note = "consider enabling one of the `critical-section` feature or `unsafe-assume-single-core` feature (or `portable_atomic_unsafe_assume_single_core` cfg)",
4979            note = "see <https://docs.rs/portable-atomic/latest/portable_atomic/#optional-features> for more."
4980        )
4981    )]
4982    pub trait HasFetchPtrAdd {}
4983    #[doc(hidden)]
4984    #[cfg_attr(
4985        not(portable_atomic_no_diagnostic_namespace),
4986        diagnostic::on_unimplemented(
4987            message = "`fetch_ptr_sub` requires atomic CAS but not available on this target by default",
4988            label = "this associated function is not available on this target by default",
4989            note = "consider enabling one of the `critical-section` feature or `unsafe-assume-single-core` feature (or `portable_atomic_unsafe_assume_single_core` cfg)",
4990            note = "see <https://docs.rs/portable-atomic/latest/portable_atomic/#optional-features> for more."
4991        )
4992    )]
4993    pub trait HasFetchPtrSub {}
4994    #[doc(hidden)]
4995    #[cfg_attr(
4996        not(portable_atomic_no_diagnostic_namespace),
4997        diagnostic::on_unimplemented(
4998            message = "`fetch_byte_add` requires atomic CAS but not available on this target by default",
4999            label = "this associated function is not available on this target by default",
5000            note = "consider enabling one of the `critical-section` feature or `unsafe-assume-single-core` feature (or `portable_atomic_unsafe_assume_single_core` cfg)",
5001            note = "see <https://docs.rs/portable-atomic/latest/portable_atomic/#optional-features> for more."
5002        )
5003    )]
5004    pub trait HasFetchByteAdd {}
5005    #[doc(hidden)]
5006    #[cfg_attr(
5007        not(portable_atomic_no_diagnostic_namespace),
5008        diagnostic::on_unimplemented(
5009            message = "`fetch_byte_sub` requires atomic CAS but not available on this target by default",
5010            label = "this associated function is not available on this target by default",
5011            note = "consider enabling one of the `critical-section` feature or `unsafe-assume-single-core` feature (or `portable_atomic_unsafe_assume_single_core` cfg)",
5012            note = "see <https://docs.rs/portable-atomic/latest/portable_atomic/#optional-features> for more."
5013        )
5014    )]
5015    pub trait HasFetchByteSub {}
5016    #[doc(hidden)]
5017    #[cfg_attr(
5018        not(portable_atomic_no_diagnostic_namespace),
5019        diagnostic::on_unimplemented(
5020            message = "`fetch_and` requires atomic CAS but not available on this target by default",
5021            label = "this associated function is not available on this target by default",
5022            note = "consider enabling one of the `critical-section` feature or `unsafe-assume-single-core` feature (or `portable_atomic_unsafe_assume_single_core` cfg)",
5023            note = "see <https://docs.rs/portable-atomic/latest/portable_atomic/#optional-features> for more."
5024        )
5025    )]
5026    pub trait HasFetchAnd {}
5027    #[doc(hidden)]
5028    #[cfg_attr(
5029        not(portable_atomic_no_diagnostic_namespace),
5030        diagnostic::on_unimplemented(
5031            message = "`and` requires atomic CAS but not available on this target by default",
5032            label = "this associated function is not available on this target by default",
5033            note = "consider enabling one of the `critical-section` feature or `unsafe-assume-single-core` feature (or `portable_atomic_unsafe_assume_single_core` cfg)",
5034            note = "see <https://docs.rs/portable-atomic/latest/portable_atomic/#optional-features> for more."
5035        )
5036    )]
5037    pub trait HasAnd {}
5038    } // cfg_no_atomic_cas_or_amo32!
5039    #[doc(hidden)]
5040    #[cfg_attr(
5041        not(portable_atomic_no_diagnostic_namespace),
5042        diagnostic::on_unimplemented(
5043            message = "`fetch_nand` requires atomic CAS but not available on this target by default",
5044            label = "this associated function is not available on this target by default",
5045            note = "consider enabling one of the `critical-section` feature or `unsafe-assume-single-core` feature (or `portable_atomic_unsafe_assume_single_core` cfg)",
5046            note = "see <https://docs.rs/portable-atomic/latest/portable_atomic/#optional-features> for more."
5047        )
5048    )]
5049    pub trait HasFetchNand {}
5050    cfg_no_atomic_cas_or_amo32! {
5051    #[doc(hidden)]
5052    #[cfg_attr(
5053        not(portable_atomic_no_diagnostic_namespace),
5054        diagnostic::on_unimplemented(
5055            message = "`fetch_or` requires atomic CAS but not available on this target by default",
5056            label = "this associated function is not available on this target by default",
5057            note = "consider enabling one of the `critical-section` feature or `unsafe-assume-single-core` feature (or `portable_atomic_unsafe_assume_single_core` cfg)",
5058            note = "see <https://docs.rs/portable-atomic/latest/portable_atomic/#optional-features> for more."
5059        )
5060    )]
5061    pub trait HasFetchOr {}
5062    #[doc(hidden)]
5063    #[cfg_attr(
5064        not(portable_atomic_no_diagnostic_namespace),
5065        diagnostic::on_unimplemented(
5066            message = "`or` requires atomic CAS but not available on this target by default",
5067            label = "this associated function is not available on this target by default",
5068            note = "consider enabling one of the `critical-section` feature or `unsafe-assume-single-core` feature (or `portable_atomic_unsafe_assume_single_core` cfg)",
5069            note = "see <https://docs.rs/portable-atomic/latest/portable_atomic/#optional-features> for more."
5070        )
5071    )]
5072    pub trait HasOr {}
5073    #[doc(hidden)]
5074    #[cfg_attr(
5075        not(portable_atomic_no_diagnostic_namespace),
5076        diagnostic::on_unimplemented(
5077            message = "`fetch_xor` requires atomic CAS but not available on this target by default",
5078            label = "this associated function is not available on this target by default",
5079            note = "consider enabling one of the `critical-section` feature or `unsafe-assume-single-core` feature (or `portable_atomic_unsafe_assume_single_core` cfg)",
5080            note = "see <https://docs.rs/portable-atomic/latest/portable_atomic/#optional-features> for more."
5081        )
5082    )]
5083    pub trait HasFetchXor {}
5084    #[doc(hidden)]
5085    #[cfg_attr(
5086        not(portable_atomic_no_diagnostic_namespace),
5087        diagnostic::on_unimplemented(
5088            message = "`xor` requires atomic CAS but not available on this target by default",
5089            label = "this associated function is not available on this target by default",
5090            note = "consider enabling one of the `critical-section` feature or `unsafe-assume-single-core` feature (or `portable_atomic_unsafe_assume_single_core` cfg)",
5091            note = "see <https://docs.rs/portable-atomic/latest/portable_atomic/#optional-features> for more."
5092        )
5093    )]
5094    pub trait HasXor {}
5095    #[doc(hidden)]
5096    #[cfg_attr(
5097        not(portable_atomic_no_diagnostic_namespace),
5098        diagnostic::on_unimplemented(
5099            message = "`fetch_not` requires atomic CAS but not available on this target by default",
5100            label = "this associated function is not available on this target by default",
5101            note = "consider enabling one of the `critical-section` feature or `unsafe-assume-single-core` feature (or `portable_atomic_unsafe_assume_single_core` cfg)",
5102            note = "see <https://docs.rs/portable-atomic/latest/portable_atomic/#optional-features> for more."
5103        )
5104    )]
5105    pub trait HasFetchNot {}
5106    #[doc(hidden)]
5107    #[cfg_attr(
5108        not(portable_atomic_no_diagnostic_namespace),
5109        diagnostic::on_unimplemented(
5110            message = "`not` requires atomic CAS but not available on this target by default",
5111            label = "this associated function is not available on this target by default",
5112            note = "consider enabling one of the `critical-section` feature or `unsafe-assume-single-core` feature (or `portable_atomic_unsafe_assume_single_core` cfg)",
5113            note = "see <https://docs.rs/portable-atomic/latest/portable_atomic/#optional-features> for more."
5114        )
5115    )]
5116    pub trait HasNot {}
5117    } // cfg_no_atomic_cas_or_amo32!
5118    #[doc(hidden)]
5119    #[cfg_attr(
5120        not(portable_atomic_no_diagnostic_namespace),
5121        diagnostic::on_unimplemented(
5122            message = "`fetch_neg` requires atomic CAS but not available on this target by default",
5123            label = "this associated function is not available on this target by default",
5124            note = "consider enabling one of the `critical-section` feature or `unsafe-assume-single-core` feature (or `portable_atomic_unsafe_assume_single_core` cfg)",
5125            note = "see <https://docs.rs/portable-atomic/latest/portable_atomic/#optional-features> for more."
5126        )
5127    )]
5128    pub trait HasFetchNeg {}
5129    #[doc(hidden)]
5130    #[cfg_attr(
5131        not(portable_atomic_no_diagnostic_namespace),
5132        diagnostic::on_unimplemented(
5133            message = "`neg` requires atomic CAS but not available on this target by default",
5134            label = "this associated function is not available on this target by default",
5135            note = "consider enabling one of the `critical-section` feature or `unsafe-assume-single-core` feature (or `portable_atomic_unsafe_assume_single_core` cfg)",
5136            note = "see <https://docs.rs/portable-atomic/latest/portable_atomic/#optional-features> for more."
5137        )
5138    )]
5139    pub trait HasNeg {}
5140    cfg_no_atomic_cas_or_amo32! {
5141    #[cfg(feature = "float")]
5142    #[cfg_attr(target_pointer_width = "16", allow(dead_code, unreachable_pub))]
5143    #[doc(hidden)]
5144    #[cfg_attr(
5145        not(portable_atomic_no_diagnostic_namespace),
5146        diagnostic::on_unimplemented(
5147            message = "`fetch_abs` requires atomic CAS but not available on this target by default",
5148            label = "this associated function is not available on this target by default",
5149            note = "consider enabling one of the `critical-section` feature or `unsafe-assume-single-core` feature (or `portable_atomic_unsafe_assume_single_core` cfg)",
5150            note = "see <https://docs.rs/portable-atomic/latest/portable_atomic/#optional-features> for more."
5151        )
5152    )]
5153    pub trait HasFetchAbs {}
5154    } // cfg_no_atomic_cas_or_amo32!
5155    #[doc(hidden)]
5156    #[cfg_attr(
5157        not(portable_atomic_no_diagnostic_namespace),
5158        diagnostic::on_unimplemented(
5159            message = "`fetch_min` requires atomic CAS but not available on this target by default",
5160            label = "this associated function is not available on this target by default",
5161            note = "consider enabling one of the `critical-section` feature or `unsafe-assume-single-core` feature (or `portable_atomic_unsafe_assume_single_core` cfg)",
5162            note = "see <https://docs.rs/portable-atomic/latest/portable_atomic/#optional-features> for more."
5163        )
5164    )]
5165    pub trait HasFetchMin {}
5166    #[doc(hidden)]
5167    #[cfg_attr(
5168        not(portable_atomic_no_diagnostic_namespace),
5169        diagnostic::on_unimplemented(
5170            message = "`fetch_max` requires atomic CAS but not available on this target by default",
5171            label = "this associated function is not available on this target by default",
5172            note = "consider enabling one of the `critical-section` feature or `unsafe-assume-single-core` feature (or `portable_atomic_unsafe_assume_single_core` cfg)",
5173            note = "see <https://docs.rs/portable-atomic/latest/portable_atomic/#optional-features> for more."
5174        )
5175    )]
5176    pub trait HasFetchMax {}
5177    #[doc(hidden)]
5178    #[cfg_attr(
5179        not(portable_atomic_no_diagnostic_namespace),
5180        diagnostic::on_unimplemented(
5181            message = "`fetch_update` requires atomic CAS but not available on this target by default",
5182            label = "this associated function is not available on this target by default",
5183            note = "consider enabling one of the `critical-section` feature or `unsafe-assume-single-core` feature (or `portable_atomic_unsafe_assume_single_core` cfg)",
5184            note = "see <https://docs.rs/portable-atomic/latest/portable_atomic/#optional-features> for more."
5185        )
5186    )]
5187    pub trait HasFetchUpdate {}
5188    cfg_no_atomic_cas_or_amo32! {
5189    #[doc(hidden)]
5190    #[cfg_attr(
5191        not(portable_atomic_no_diagnostic_namespace),
5192        diagnostic::on_unimplemented(
5193            message = "`bit_set` requires atomic CAS but not available on this target by default",
5194            label = "this associated function is not available on this target by default",
5195            note = "consider enabling one of the `critical-section` feature or `unsafe-assume-single-core` feature (or `portable_atomic_unsafe_assume_single_core` cfg)",
5196            note = "see <https://docs.rs/portable-atomic/latest/portable_atomic/#optional-features> for more."
5197        )
5198    )]
5199    pub trait HasBitSet {}
5200    #[doc(hidden)]
5201    #[cfg_attr(
5202        not(portable_atomic_no_diagnostic_namespace),
5203        diagnostic::on_unimplemented(
5204            message = "`bit_clear` requires atomic CAS but not available on this target by default",
5205            label = "this associated function is not available on this target by default",
5206            note = "consider enabling one of the `critical-section` feature or `unsafe-assume-single-core` feature (or `portable_atomic_unsafe_assume_single_core` cfg)",
5207            note = "see <https://docs.rs/portable-atomic/latest/portable_atomic/#optional-features> for more."
5208        )
5209    )]
5210    pub trait HasBitClear {}
5211    #[doc(hidden)]
5212    #[cfg_attr(
5213        not(portable_atomic_no_diagnostic_namespace),
5214        diagnostic::on_unimplemented(
5215            message = "`bit_toggle` requires atomic CAS but not available on this target by default",
5216            label = "this associated function is not available on this target by default",
5217            note = "consider enabling one of the `critical-section` feature or `unsafe-assume-single-core` feature (or `portable_atomic_unsafe_assume_single_core` cfg)",
5218            note = "see <https://docs.rs/portable-atomic/latest/portable_atomic/#optional-features> for more."
5219        )
5220    )]
5221    pub trait HasBitToggle {}
5222    } // cfg_no_atomic_cas_or_amo32!
5223}
5224} // cfg_no_atomic_cas!