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