atomic_float/
atomic_f32.rs

1use core::cell::UnsafeCell;
2use core::sync::atomic::{
3    AtomicU32,
4    Ordering::{self, *},
5};
6
7/// A floating point type which can be safely shared between threads.
8///
9/// This type has the same in-memory representation as the underlying floating
10/// point type, [`f32`].
11///
12/// See the module documentation for [core::sync::atomic] for information about
13/// the portability of various atomics (this one is mostly as portable as
14/// [`AtomicU32`](core::sync::atomic::AtomicU32), with the caveat that we
15/// additionally that the platform support 32-bit floats).
16///
17/// # Example
18///
19/// The intended use case is situations like this:
20///
21/// ```
22/// # use atomic_float::AtomicF32;
23/// # use std::sync::atomic::Ordering;
24/// static DELTA_TIME: AtomicF32 = AtomicF32::new(1.0);
25///
26/// // In some main simulation loop:
27/// # fn compute_delta_time() -> f32 { 1.0 / 60.0 }
28/// DELTA_TIME.store(compute_delta_time(), Ordering::Release);
29///
30/// // elsewhere, perhaps on other threads:
31/// let dt = DELTA_TIME.load(Ordering::Acquire);
32/// // Use `dt` to compute simulation...
33/// ```
34///
35/// As well as any other cases where use of locking would be too substantial of
36/// overhead.
37///
38/// Note that when used like this (with Acquire and Release orderings), on
39/// x86_64 this compiles to the same code as you would get from a C++ global,
40/// (or a Rust `static mut`), while offering full synchronization.
41///
42/// (While caveats exist, the cases where you'd need the total order guaranteed
43/// by [SeqCst](core::sync::atomic::Ordering::SeqCst) for something like
44/// [`AtomicF32`] seem very rare).
45///
46/// # Implementation
47///
48/// Note: These details are not part of the stability guarantee of this crate,
49/// and are subject to change without a semver-breaking change.
50///
51/// Under the hood we use a transparent `UnsafeCell<f32>`, and cast the
52/// `&UnsafeCell<f32>` to an [`&AtomicU32`](core::sync::atomic::AtomicU32) in
53/// order to perform atomic operations.
54///
55/// This means that we have the same ABI and layout as f32, and that some
56/// operations have a minimal cost (for example: on x86 all operations of
57/// equivalent or weaker ordering than `Release` stores/`Acquire` loads are
58/// essentially equivalent to non-atomic f32).
59///
60/// However, operations like [`fetch_add`](AtomicF32::fetch_add) are
61/// considerably slower than would be the case for integer atomics.
62#[repr(transparent)]
63pub struct AtomicF32(
64    // FIXME: Once we can do `f32::from_bits` in const fn, this should be an
65    // `AtomicU32` (or at least `UnsafeCell<u32>`).
66    UnsafeCell<f32>,
67);
68
69// SAFETY: We only ever access the underlying data by refcasting to AtomicU32,
70// which guarantees no data races.
71unsafe impl Send for AtomicF32 {}
72unsafe impl Sync for AtomicF32 {}
73
74// Static assertions that the layout is identical, we cite these in a safety
75// comment in `AtomicF32::atom()`. Note that the alignment check is stricter
76// than we need, as it would still be safe if `AtomicU32` is less strictly-
77// aligned than our `f32`. Unlike with `AtomicF64`, this is unlikely to occur.
78const _: [(); core::mem::size_of::<AtomicU32>()] = [(); core::mem::size_of::<UnsafeCell<f32>>()];
79const _: [(); core::mem::align_of::<AtomicU32>()] = [(); core::mem::align_of::<UnsafeCell<f32>>()];
80
81impl AtomicF32 {
82    /// Initialize a `AtomicF32` from an `f32`.
83    ///
84    /// # Example
85    ///
86    /// Use as a variable
87    ///
88    /// ```
89    /// # use atomic_float::AtomicF32;
90    /// # use std::sync::atomic::Ordering::Relaxed;
91    /// let x = AtomicF32::new(3.0f32);
92    /// assert_eq!(x.load(Relaxed), 3.0f32);
93    /// ```
94    ///
95    /// Use as a static:
96    ///
97    /// ```
98    /// # use atomic_float::AtomicF32;
99    /// # use std::sync::atomic::Ordering::Relaxed;
100    /// static A_STATIC: AtomicF32 = AtomicF32::new(800.0);
101    /// assert_eq!(A_STATIC.load(Relaxed), 800.0);
102    /// ```
103    #[inline]
104    pub const fn new(float: f32) -> Self {
105        Self(UnsafeCell::new(float))
106    }
107
108    /// Returns a mutable reference to the underlying float.
109    ///
110    /// This is safe because the mutable reference guarantees that no other
111    /// threads are concurrently accessing the atomic data.
112    ///
113    /// # Example
114    ///
115    /// ```
116    /// # use atomic_float::AtomicF32;
117    /// # use std::sync::atomic::Ordering;
118    /// let mut some_float = AtomicF32::new(1.0);
119    /// assert_eq!(*some_float.get_mut(), 1.0);
120    /// *some_float.get_mut() += 1.0;
121    /// assert_eq!(some_float.load(Ordering::SeqCst), 2.0);
122    /// ```
123    #[inline]
124    pub fn get_mut(&mut self) -> &mut f32 {
125        // SAFETY: the mutable reference guarantees unique ownership.
126        unsafe { &mut *self.0.get() }
127    }
128
129    /// Consumes the atomic and returns the contained value.
130    ///
131    /// This is safe because passing `self` by value guarantees that no other
132    /// threads are concurrently accessing the atomic data.
133    ///
134    /// # Example
135    ///
136    /// ```
137    /// # use atomic_float::AtomicF32;
138    /// let v = AtomicF32::new(6.0);
139    /// assert_eq!(v.into_inner(), 6.0f32);
140    /// ```
141    #[inline]
142    pub fn into_inner(self) -> f32 {
143        self.0.into_inner()
144    }
145
146    /// Loads a value from the atomic float.
147    ///
148    /// `load` takes an [`Ordering`] argument which describes the memory
149    /// ordering of this operation. Possible values are [`SeqCst`], [`Acquire`]
150    /// and [`Relaxed`].
151    ///
152    /// # Panics
153    ///
154    /// Panics if `ordering` is [`Release`] or [`AcqRel`].
155    ///
156    /// [`Ordering`]: core::sync::atomic::Ordering
157    /// [`Relaxed`]: core::sync::atomic::Ordering::Relaxed
158    /// [`Release`]: core::sync::atomic::Ordering::Release
159    /// [`Acquire`]: core::sync::atomic::Ordering::Acquire
160    /// [`AcqRel`]: core::sync::atomic::Ordering::AcqRel
161    /// [`SeqCst`]: core::sync::atomic::Ordering::SeqCst
162    ///
163    /// # Example
164    ///
165    /// ```
166    /// use atomic_float::AtomicF32;
167    /// use std::sync::atomic::Ordering;
168    /// let v = AtomicF32::new(22.5);
169    /// assert_eq!(v.load(Ordering::SeqCst), 22.5);
170    /// ```
171    #[inline]
172    pub fn load(&self, ordering: Ordering) -> f32 {
173        f32::from_bits(self.as_atomic_bits().load(ordering))
174    }
175
176    /// Store a value into the atomic float.
177    ///
178    /// `store` takes an [`Ordering`] argument which describes the memory
179    /// ordering of this operation. Possible values are [`SeqCst`], [`Release`]
180    /// and [`Relaxed`].
181    ///
182    /// # Panics
183    ///
184    /// Panics if `ordering` is [`Acquire`] or [`AcqRel`].
185    ///
186    /// [`Ordering`]: core::sync::atomic::Ordering
187    /// [`Relaxed`]: core::sync::atomic::Ordering::Relaxed
188    /// [`Release`]: core::sync::atomic::Ordering::Release
189    /// [`Acquire`]: core::sync::atomic::Ordering::Acquire
190    /// [`AcqRel`]: core::sync::atomic::Ordering::AcqRel
191    /// [`SeqCst`]: core::sync::atomic::Ordering::SeqCst
192    ///
193    /// # Example
194    ///
195    /// ```
196    /// use atomic_float::AtomicF32;
197    /// use std::sync::atomic::Ordering;
198    /// let v = AtomicF32::new(22.5);
199    /// assert_eq!(v.load(Ordering::SeqCst), 22.5);
200    /// v.store(30.0, Ordering::SeqCst);
201    /// assert_eq!(v.load(Ordering::SeqCst), 30.0);
202    /// ```
203    #[inline]
204    pub fn store(&self, value: f32, ordering: Ordering) {
205        self.as_atomic_bits().store(value.to_bits(), ordering);
206    }
207
208    /// Stores a value into the atomic float, returning the previous value.
209    ///
210    /// `swap` takes an [`Ordering`] argument which describes the memory ordering
211    /// of this operation. All ordering modes are possible. Note that using
212    /// [`Acquire`] makes the store part of this operation [`Relaxed`], and
213    /// using [`Release`] makes the load part [`Relaxed`].
214    ///
215    /// [`Ordering`]: core::sync::atomic::Ordering
216    /// [`Relaxed`]: core::sync::atomic::Ordering::Relaxed
217    /// [`Release`]: core::sync::atomic::Ordering::Release
218    /// [`Acquire`]: core::sync::atomic::Ordering::Acquire
219    ///
220    /// # Example
221    ///
222    /// ```
223    /// use atomic_float::AtomicF32;
224    /// use std::sync::atomic::Ordering;
225    /// let v = AtomicF32::new(4.5);
226    /// assert_eq!(v.swap(100.0, Ordering::Relaxed), 4.5);
227    /// assert_eq!(v.load(Ordering::Relaxed), 100.0);
228    /// ```
229    #[inline]
230    #[cfg(target_has_atomic = "32")]
231    pub fn swap(&self, new_value: f32, ordering: Ordering) -> f32 {
232        f32::from_bits(self.as_atomic_bits().swap(new_value.to_bits(), ordering))
233    }
234
235    /// Stores a value into the atomic float if the current value is *bitwise
236    /// identical* to the `current` value.
237    ///
238    /// The return value is always the previous value. If it is equal to
239    /// `current`, then the value was updated.
240    ///
241    /// `compare_and_swap` also takes an [`Ordering`] argument which describes
242    /// the memory ordering of this operation. Notice that even when using
243    /// `AcqRel`, the operation might fail and hence just perform an `Acquire`
244    /// load, but not have `Release` semantics. Using `Acquire` makes the store
245    /// part of this operation `Relaxed` if it happens, and using `Release`
246    /// makes the load part `Relaxed`.
247    ///
248    /// [`Ordering`]: core::sync::atomic::Ordering
249    ///
250    /// # Caveats
251    ///
252    /// As the `current` must be bitwise identical to the previous value, you
253    /// should not get the `current` value using any sort of arithmetic (both
254    /// because of rounding, and to avoid any situation where -0.0 and +0.0
255    /// would be compared).  Additionally, on some platforms (WASM and ASM.js
256    /// currently) LLVM will canonicalize NaNs during loads, which can cause
257    /// unexpected behavior here — typically in the other direction (two values
258    /// being unexpectedly equal).
259    ///
260    /// In practice, typical patterns for CaS tend to avoid these issues, but
261    /// you're encouraged to avoid relying on the behavior of cas-family APIs in
262    /// the face of rounding, signed zero, and NaNs.
263    ///
264    /// # Example
265    ///
266    /// ```
267    /// # use atomic_float::AtomicF32;
268    /// # use std::sync::atomic::Ordering;
269    /// let v = AtomicF32::new(5.0);
270    /// assert_eq!(v.compare_and_swap(5.0, 10.0, Ordering::Relaxed), 5.0);
271    /// assert_eq!(v.load(Ordering::Relaxed), 10.0);
272    ///
273    /// assert_eq!(v.compare_and_swap(6.0, 12.0, Ordering::Relaxed), 10.0);
274    /// assert_eq!(v.load(Ordering::Relaxed), 10.0);
275    /// ```
276    #[inline]
277    #[allow(deprecated)]
278    #[cfg(target_has_atomic = "32")]
279    pub fn compare_and_swap(&self, current: f32, new: f32, order: Ordering) -> f32 {
280        f32::from_bits(self.as_atomic_bits().compare_and_swap(
281            current.to_bits(),
282            new.to_bits(),
283            order,
284        ))
285    }
286
287    /// Stores a value into the atomic float if the current value is the bitwise
288    /// identical as the `current` value.
289    ///
290    /// The return value is a result indicating whether the new value was
291    /// written and containing the previous value. On success this value is
292    /// guaranteed to be bitwise identical to `current`.
293    ///
294    /// `compare_exchange` takes two [`Ordering`] arguments to describe the
295    /// memory ordering of this operation. The first describes the required
296    /// ordering if the operation succeeds while the second describes the
297    /// required ordering when the operation fails. Using `Acquire` as success
298    /// ordering makes the store part of this operation `Relaxed`, and using
299    /// `Release` makes the successful load `Relaxed`. The failure ordering can
300    /// only be `SeqCst`, `Acquire` or `Relaxed` and must be equivalent to or
301    /// weaker than the success ordering.
302    ///
303    /// [`Ordering`]: core::sync::atomic::Ordering
304    ///
305    /// # Notes
306    ///
307    /// Note that in many cases, when `while` loops where the condition contains
308    /// a `compare_exchange` operation are better written to use a
309    /// [`compare_exchange_weak`](AtomicF32::compare_exchange_weak) in the
310    /// condition instead (as on weakly ordered platforms like ARM, the
311    /// `compare_exchange` operation itself can require a loop to perform).
312    ///
313    /// ## Caveats
314    ///
315    /// As the `current` parameter must be bitwise identical to the previous
316    /// value, you should not get the `current` value using any sort of
317    /// arithmetic (both because of rounding, and to avoid any situation where
318    /// -0.0 and +0.0 would be compared). Additionally, on Wasm, in some cases
319    /// `NaN` values have been known to cause problems for non-typical usage of
320    /// this API. See [`AtomicF32::as_atomic_bits`] if performing the
321    /// `compare_exchange` on the raw bits of this atomic float would solve an
322    /// issue for you.
323    ///
324    /// # Example
325    ///
326    /// ```
327    /// # use atomic_float::AtomicF32;
328    /// # use std::sync::atomic::Ordering::*;
329    /// let v = AtomicF32::new(5.0);
330    /// assert_eq!(v.compare_exchange(5.0, 10.0, Acquire, Relaxed), Ok(5.0));
331    /// assert_eq!(v.load(Relaxed), 10.0);
332    ///
333    /// assert_eq!(v.compare_exchange(6.0, 12.0, SeqCst, Relaxed), Err(10.0));
334    /// assert_eq!(v.load(Relaxed), 10.0);
335    /// ```
336    #[inline]
337    #[cfg(target_has_atomic = "32")]
338    pub fn compare_exchange(
339        &self,
340        current: f32,
341        new: f32,
342        success: Ordering,
343        failure: Ordering,
344    ) -> Result<f32, f32> {
345        convert_result(self.as_atomic_bits().compare_exchange(
346            current.to_bits(),
347            new.to_bits(),
348            success,
349            failure,
350        ))
351    }
352
353    /// Stores a value into the atomic integer if the current value is the same
354    /// as the `current` value.
355    ///
356    /// Unlike [`compare_exchange`](Self::compare_exchange), this function is
357    /// allowed to spuriously fail even when the comparison succeeds, which can
358    /// result in more efficient code on some platforms. The return value is a
359    /// result indicating whether the new value was written and containing the
360    /// previous value.
361    ///
362    /// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the
363    /// memory ordering of this operation. The first describes the required
364    /// ordering if the operation succeeds while the second describes the
365    /// required ordering when the operation fails. Using `Acquire` as success
366    /// ordering makes the store part of this operation `Relaxed`, and using
367    /// `Release` makes the successful load `Relaxed`. The failure ordering can
368    /// only be `SeqCst`, `Acquire` or `Relaxed` and must be equivalent to or
369    /// weaker than the success ordering.
370    ///
371    /// [`Ordering`]: core::sync::atomic::Ordering
372    ///
373    /// ## Caveats
374    ///
375    /// As the `current` parameter must be bitwise identical to the previous
376    /// value, you should not get the `current` value using any sort of
377    /// arithmetic (both because of rounding, and to avoid any situation where
378    /// -0.0 and +0.0 would be compared). Additionally, on Wasm, in some cases
379    /// `NaN` values have been known to cause problems for non-typical usage of
380    /// this API. See [`AtomicF32::as_atomic_bits`] if performing the
381    /// `compare_exchange` on the raw bits of this atomic float would solve an
382    /// issue for you.
383    ///
384    /// # Example
385    ///
386    /// Note that this sort of CaS loop should generally use [`fetch_update`]
387    /// instead.
388    ///
389    /// [`fetch_update`]: AtomicF32::fetch_update
390    ///
391    /// ```
392    /// # use atomic_float::AtomicF32;
393    /// # use std::sync::atomic::Ordering::*;
394    /// let v = AtomicF32::new(5.0);
395    /// let mut old = v.load(Relaxed);
396    /// loop {
397    ///     let new = old * 2.0;
398    ///     match v.compare_exchange_weak(old, new, SeqCst, Relaxed) {
399    ///         Ok(_) => break,
400    ///         Err(x) => old = x,
401    ///     }
402    /// }
403    /// ```
404    #[inline]
405    #[cfg(target_has_atomic = "32")]
406    pub fn compare_exchange_weak(
407        &self,
408        current: f32,
409        new: f32,
410        success: Ordering,
411        failure: Ordering,
412    ) -> Result<f32, f32> {
413        convert_result(self.as_atomic_bits().compare_exchange_weak(
414            current.to_bits(),
415            new.to_bits(),
416            success,
417            failure,
418        ))
419    }
420
421    /// Fetches the value, and applies a function to it that returns an optional
422    /// new value. Returns a `Result` of `Ok(previous_value)` if the function
423    /// returned `Some(_)`, else `Err(previous_value)`.
424    ///
425    /// Note: This may call the function multiple times if the value has been
426    /// changed from other threads in the meantime, as long as the function
427    /// returns `Some(_)`, but the function will have been applied only once to
428    /// the stored value.
429    ///
430    /// `fetch_update` takes two [`Ordering`] arguments to describe the memory
431    /// ordering of this operation. The first describes the required ordering
432    /// for when the operation finally succeeds while the second describes the
433    /// required ordering for loads. These correspond to the success and failure
434    /// orderings of [`compare_exchange`][AtomicF32::compare_exchange]
435    /// respectively.
436    ///
437    /// Using `Acquire` as success ordering makes the store part of this
438    /// operation `Relaxed`, and using `Release` makes the final successful load
439    /// `Relaxed`. The (failed) load ordering can only be `SeqCst`, `Acquire` or
440    /// `Relaxed` and must be equivalent to or weaker than the success ordering.
441    ///
442    /// [`Ordering`]: core::sync::atomic::Ordering
443    ///
444    /// # Example
445    ///
446    /// ```
447    /// # use atomic_float::AtomicF32;
448    /// # use std::sync::atomic::Ordering::*;
449    /// let x = AtomicF32::new(7.0);
450    ///
451    /// assert_eq!(x.fetch_update(SeqCst, SeqCst, |_| None), Err(7.0));
452    /// assert_eq!(x.fetch_update(SeqCst, SeqCst, |x| Some(x + 1.0)), Ok(7.0));
453    /// assert_eq!(x.fetch_update(SeqCst, SeqCst, |x| Some(x + 1.0)), Ok(8.0));
454    /// assert_eq!(x.load(SeqCst), 9.0);
455    /// ```
456    #[inline]
457    #[cfg(target_has_atomic = "32")]
458    pub fn fetch_update<F>(
459        &self,
460        set_order: Ordering,
461        fetch_order: Ordering,
462        mut update: F,
463    ) -> Result<f32, f32>
464    where
465        F: FnMut(f32) -> Option<f32>,
466    {
467        let res = self
468            .as_atomic_bits()
469            .fetch_update(set_order, fetch_order, |prev| {
470                update(f32::from_bits(prev)).map(f32::to_bits)
471            });
472        convert_result(res)
473    }
474
475    /// A (nonstandard) convenience wrapper around [`fetch_update`](Self::fetch_update).
476    ///
477    /// A call like:
478    ///
479    /// ```
480    /// # const _: &str = stringify!{
481    /// let res = atom.update_with(order, |f| update f...);
482    /// # };
483    /// ```
484    ///
485    /// Is morally equivalent to:
486    ///
487    /// ```
488    /// # const _: &str = stringify!{
489    /// let res = atom.fetch_update(
490    ///     order,
491    ///     failure_order_for(order),
492    ///     |f| Some(update f...),
493    /// ).unwrap();
494    /// # };
495    /// ```
496    ///
497    /// Where `failure_order_for` returns the strongest failure order you'd be
498    /// allowed to pass into `fetch_update` given the success order, that is:
499    ///
500    /// ```
501    /// # const _: &str = stringify!{
502    /// fn failure_order_for(order: Ordering) -> Ordering {
503    ///     Release | Relaxed => Relaxed,
504    ///     Acquire | AcqRel => Acquire,
505    ///     SeqCst => SeqCst,
506    /// }
507    /// # };
508    /// ```
509    #[inline]
510    #[cfg(target_has_atomic = "32")]
511    fn update_with<F>(&self, order: Ordering, mut update: F) -> f32
512    where
513        F: FnMut(f32) -> f32,
514    {
515        self.fetch_update(order, super::fail_order_for(order), |f| Some(update(f)))
516            .unwrap()
517    }
518
519    /// Adds to the current value, returning the previous value.
520    ///
521    /// Because this returns the previous value, you may want to call it like:
522    /// `atom.fetch_add(x, order) + x`
523    ///
524    /// # Examples
525    /// ```
526    /// # use atomic_float::AtomicF32;
527    /// # use std::sync::atomic::Ordering::*;
528    /// let x = AtomicF32::new(7.0);
529    ///
530    /// assert_eq!(x.fetch_add(2.0, Relaxed), 7.0);
531    /// assert_eq!(x.fetch_add(1.0, SeqCst), 9.0);
532    /// assert_eq!(x.fetch_add(-100.0, AcqRel), 10.0);
533    /// ```
534    #[inline]
535    #[cfg(target_has_atomic = "32")]
536    pub fn fetch_add(&self, val: f32, order: Ordering) -> f32 {
537        self.update_with(order, |f| f + val)
538    }
539
540    /// Subtract from the current value, returning the previous value.
541    ///
542    /// Because this returns the previous value, you may want to call it like:
543    /// `atom.fetch_sub(x, order) - x`
544    ///
545    /// Note: This operation uses [`fetch_update`](Self::fetch_update) under the hood, and is likely
546    /// to be slower than the equivalent operation for atomic integers.
547    ///
548    /// # Examples
549    /// ```
550    /// # use atomic_float::AtomicF32;
551    /// # use std::sync::atomic::Ordering::*;
552    /// let x = AtomicF32::new(7.0);
553    /// assert_eq!(x.fetch_sub(2.0, Relaxed), 7.0);
554    /// assert_eq!(x.fetch_sub(-1.0, SeqCst), 5.0);
555    /// assert_eq!(x.fetch_sub(0.5, AcqRel), 6.0);
556    /// ```
557    #[inline]
558    #[cfg(target_has_atomic = "32")]
559    pub fn fetch_sub(&self, val: f32, order: Ordering) -> f32 {
560        self.update_with(order, |f| f - val)
561    }
562
563    /// Produce the absolute value of the current value, returning the previous
564    /// value.
565    ///
566    /// # Examples
567    /// ```
568    /// # use atomic_float::AtomicF32;
569    /// # use std::sync::atomic::Ordering::*;
570    /// let x = AtomicF32::new(-7.0);
571    /// assert_eq!(x.fetch_abs(Relaxed), -7.0);
572    /// assert_eq!(x.fetch_abs(SeqCst), 7.0);
573    /// ```
574    #[inline]
575    #[cfg(target_has_atomic = "32")]
576    pub fn fetch_abs(&self, order: Ordering) -> f32 {
577        f32::from_bits(self.as_atomic_bits().fetch_and(0x7fff_ffff, order))
578    }
579
580    /// Negates the current value, returning the previous value.
581    ///
582    /// As a result of returning the previous value, you may want to invoke it like:
583    /// `-atom.fetch_neg(Relaxed)`.
584    ///
585    ///
586    /// # Examples
587    /// ```
588    /// # use atomic_float::AtomicF32;
589    /// # use std::sync::atomic::Ordering::*;
590    /// let x = AtomicF32::new(-7.0);
591    /// assert_eq!(x.fetch_neg(Relaxed), -7.0);
592    /// assert_eq!(x.fetch_neg(SeqCst), 7.0);
593    /// assert_eq!(x.fetch_neg(AcqRel), -7.0);
594    /// ```
595    #[inline]
596    #[cfg(target_has_atomic = "32")]
597    pub fn fetch_neg(&self, order: Ordering) -> f32 {
598        f32::from_bits(self.as_atomic_bits().fetch_xor(0x8000_0000, order))
599    }
600
601    /// Minimum with the current value.
602    ///
603    /// Finds the minimum of the current value and the argument `val`, and sets
604    /// the new value to the result.
605    ///
606    /// Returns the previous value. Because of this, you may want to call it
607    /// like: `atom.fetch_min(x, order).min(x)`
608    ///
609    /// Note: This operation uses [`fetch_update`](Self::fetch_update) under the
610    /// hood, and is likely to be slower than the equivalent operation for
611    /// atomic integers.
612    ///
613    /// # Examples
614    ///
615    /// ```
616    /// # use atomic_float::AtomicF32;
617    /// # use std::sync::atomic::Ordering;
618    ///
619    /// let foo = AtomicF32::new(23.0);
620    /// assert_eq!(foo.fetch_min(42.0, Ordering::Relaxed), 23.0);
621    /// assert_eq!(foo.load(Ordering::Relaxed), 23.0);
622    /// assert_eq!(foo.fetch_min(22.0, Ordering::Relaxed), 23.0);
623    /// assert_eq!(foo.load(Ordering::Relaxed), 22.0);
624    /// ```
625    #[inline]
626    #[cfg(target_has_atomic = "32")]
627    pub fn fetch_min(&self, value: f32, order: Ordering) -> f32 {
628        self.update_with(order, |f| f.min(value))
629    }
630
631    /// Maximum with the current value.
632    ///
633    /// Finds the maximum of the current value and the argument `val`, and sets
634    /// the new value to the result.
635    ///
636    /// Returns the previous value. Because of this, you may want to call it
637    /// like: `atom.fetch_max(x, order).max(x)`
638    ///
639    /// Note: This operation uses [`fetch_update`](Self::fetch_update) under the
640    /// hood, and is likely to be slower than the equivalent operation for
641    /// atomic integers.
642    ///
643    /// # Examples
644    ///
645    /// ```
646    /// # use atomic_float::AtomicF32;
647    /// # use std::sync::atomic::Ordering;
648    ///
649    /// let foo = AtomicF32::new(23.0);
650    /// assert_eq!(foo.fetch_max(22.0, Ordering::Relaxed), 23.0);
651    /// assert_eq!(foo.load(Ordering::Relaxed), 23.0);
652    /// assert_eq!(foo.fetch_max(42.0, Ordering::Relaxed), 23.0);
653    /// assert_eq!(foo.load(Ordering::Relaxed), 42.0);
654    /// ```
655    #[inline]
656    #[cfg(target_has_atomic = "32")]
657    pub fn fetch_max(&self, value: f32, order: Ordering) -> f32 {
658        self.update_with(order, |f| f.max(value))
659    }
660
661    /// Returns a reference to an atomic integer which can be used to access the
662    /// atomic float's underlying bits in a thread safe manner.
663    ///
664    /// This is essentially a `transmute::<&Self, &AtomicU32>(self)`, and is
665    /// zero cost.
666    ///
667    /// # Motivation
668    ///
669    /// This is exposed as an escape hatch because of the caveats around the
670    /// `AtomicF32` CaS-family APIs ([`compare_and_swap`], [`compare_exchange`],
671    /// [`compare_exchange_weak`], ...) and the notion of bitwise identicality
672    /// which they require being somewhat problematic for NaNs, especially on
673    /// targets like Wasm (see [rust-lang/rust#73328]).
674    ///
675    /// [`compare_and_swap`]: AtomicU32::compare_and_swap
676    /// [`compare_exchange`]: AtomicU32::compare_exchange
677    /// [`compare_exchange_weak`]: AtomicU32::compare_exchange_weak
678    /// [rust-lang/rust#73328]: https://github.com/rust-lang/rust/issues/73328
679    ///
680    /// In general despite how bad this might sound, in practice we're fairly
681    /// safe: LLVM almost never optimizes through atomic operations, this
682    /// library is written to try to avoid potential issues from most naive
683    /// usage, and I'm optimistic the situation will clean itself up in the
684    /// short-to-medium-term future.
685    ///
686    /// However, if you need peace of mind, or find yourself in a case where you
687    /// suspect you're hitting this issue, you can access the underlying atomic
688    /// value using this function.
689    ///
690    /// # Examples
691    ///
692    /// ```
693    /// # use atomic_float::AtomicF32;
694    /// # use std::sync::atomic::Ordering;
695    /// let v = AtomicF32::new(22.5);
696    /// assert_eq!(v.as_atomic_bits().load(Ordering::Relaxed), 22.5f32.to_bits());
697    /// ```
698    #[inline]
699    pub fn as_atomic_bits(&self) -> &AtomicU32 {
700        // Safety: All potentially shared reads/writes go through this, and the
701        // static assertions above ensure that AtomicU32 and UnsafeCell<f32> are
702        // compatible as pointers.
703        unsafe { &*(&self.0 as *const _ as *const AtomicU32) }
704    }
705}
706
707/// Return a zero-initialized atomic.
708///
709/// # Example
710///
711/// ```
712/// # use atomic_float::AtomicF32;
713/// # use core::sync::atomic::Ordering;
714/// let x = AtomicF32::default();
715/// assert_eq!(x.load(Ordering::SeqCst), 0.0);
716/// ```
717impl Default for AtomicF32 {
718    #[inline]
719    fn default() -> Self {
720        Self::from(0.0)
721    }
722}
723
724/// Equivalent to `<f32 as core::fmt::Debug>::fmt`.
725///
726/// # Example
727///
728/// ```
729/// # use atomic_float::AtomicF32;
730/// # use core::sync::atomic::Ordering;
731/// let v = AtomicF32::new(40.0);
732/// assert_eq!(format!("{:?}", v), format!("{:?}", 40.0f32));
733/// ```
734impl core::fmt::Debug for AtomicF32 {
735    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
736        self.load(SeqCst).fmt(f)
737    }
738}
739
740/// Equivalent to `AtomicF32::new`.
741///
742/// # Example
743///
744/// ```
745/// # use atomic_float::AtomicF32;
746/// # use core::sync::atomic::Ordering;
747/// let v = AtomicF32::from(10.0);
748/// assert_eq!(v.load(Ordering::SeqCst), 10.0);
749/// ```
750impl From<f32> for AtomicF32 {
751    #[inline]
752    fn from(f: f32) -> Self {
753        Self::new(f)
754    }
755}
756
757#[cfg(feature = "serde")]
758/// Serializes the AtomicF32
759///
760/// The value is loaded with the `Ordering::SeqCst` and then serializes
761/// it as a normal `f32`. The information about the object being atomic is lost.
762impl serde::Serialize for AtomicF32 {
763    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
764    where
765        S: serde::Serializer,
766    {
767        serializer.serialize_f32(self.load(Ordering::SeqCst))
768    }
769}
770
771#[cfg(feature = "serde")]
772/// Deserializes the AtomicF32
773///
774/// Attempts to deserialize f32 and, if successful, creates a new
775/// AtomicF32 with this value.
776impl<'de> serde::Deserialize<'de> for AtomicF32 {
777    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
778    where
779        D: serde::Deserializer<'de>,
780    {
781        f32::deserialize(deserializer).map(AtomicF32::new)
782    }
783}
784
785#[inline(always)]
786fn convert_result(r: Result<u32, u32>) -> Result<f32, f32> {
787    r.map(f32::from_bits).map_err(f32::from_bits)
788}
789
790// XXX: This is dubious since the actual atomic types don't implement this, but
791// I need it to use `serde_test`, so I might as well add it.
792/// Compare two [`AtomicF32`]s.
793///
794/// ```
795/// # use atomic_float::AtomicF32;
796/// # use std::sync::atomic::Ordering;
797/// let a = AtomicF32::new(1.0);
798/// a.fetch_add(1.0, Ordering::Relaxed);
799/// assert_ne!(a, AtomicF32::new(1.0));
800/// assert_eq!(a, AtomicF32::new(2.0));
801/// ```
802///
803/// # Caveats
804/// Relaxed ordering is used for each load, so additional fencing (or avoiding
805/// the use of this `PartialEq` implementation) may be desirable.
806///
807/// Additionally, this is implemented in terms of `f32`'s `PartialEq`, so NaNs
808/// will compare as inequal. For example:
809/// ```
810/// # use atomic_float::AtomicF32;
811/// let a = AtomicF32::new(f32::NAN);
812/// assert_ne!(a, a);
813/// ```
814impl PartialEq for AtomicF32 {
815    #[inline]
816    fn eq(&self, o: &AtomicF32) -> bool {
817        self.load(Relaxed) == o.load(Relaxed)
818    }
819}