Skip to main content

crossbeam_utils/atomic/
atomic_cell.rs

1// Necessary for implementing atomic methods for `AtomicUnit`
2#![allow(clippy::unit_arg)]
3
4use crate::primitive::sync::atomic::{self, Ordering};
5use crate::CachePadded;
6use core::cell::UnsafeCell;
7use core::cmp;
8use core::fmt;
9use core::mem::{self, ManuallyDrop, MaybeUninit};
10use core::panic::{RefUnwindSafe, UnwindSafe};
11use core::ptr;
12
13use super::seq_lock::SeqLock;
14
15/// A thread-safe mutable memory location.
16///
17/// This type is equivalent to [`Cell`], except it can also be shared among multiple threads.
18///
19/// Operations on `AtomicCell`s use atomic instructions whenever possible, and synchronize using
20/// global locks otherwise. You can call [`AtomicCell::<T>::is_lock_free()`] to check whether
21/// atomic instructions or locks will be used.
22///
23/// Atomic loads use the [`Acquire`] ordering and atomic stores use the [`Release`] ordering.
24///
25/// [`Cell`]: std::cell::Cell
26/// [`AtomicCell::<T>::is_lock_free()`]: AtomicCell::is_lock_free
27/// [`Acquire`]: std::sync::atomic::Ordering::Acquire
28/// [`Release`]: std::sync::atomic::Ordering::Release
29#[repr(transparent)]
30pub struct AtomicCell<T> {
31    /// The inner value.
32    ///
33    /// If this value can be transmuted into a primitive atomic type, it will be treated as such.
34    /// Otherwise, all potentially concurrent operations on this data will be protected by a global
35    /// lock.
36    ///
37    /// Using MaybeUninit to prevent code outside the cell from observing partially initialized state:
38    /// <https://github.com/crossbeam-rs/crossbeam/issues/833>
39    /// (This rustc bug has been fixed in Rust 1.64.)
40    ///
41    /// Note:
42    /// - we'll never store uninitialized `T` due to our API only using initialized `T`.
43    /// - this `MaybeUninit` does *not* fix <https://github.com/crossbeam-rs/crossbeam/issues/315>.
44    value: UnsafeCell<MaybeUninit<T>>,
45}
46
47unsafe impl<T: Send> Send for AtomicCell<T> {}
48unsafe impl<T: Send> Sync for AtomicCell<T> {}
49
50impl<T> UnwindSafe for AtomicCell<T> {}
51impl<T> RefUnwindSafe for AtomicCell<T> {}
52
53impl<T> AtomicCell<T> {
54    /// Creates a new atomic cell initialized with `val`.
55    ///
56    /// # Examples
57    ///
58    /// ```
59    /// use crossbeam_utils::atomic::AtomicCell;
60    ///
61    /// let a = AtomicCell::new(7);
62    /// ```
63    pub const fn new(val: T) -> AtomicCell<T> {
64        AtomicCell {
65            value: UnsafeCell::new(MaybeUninit::new(val)),
66        }
67    }
68
69    /// Consumes the atomic and returns the contained value.
70    ///
71    /// This is safe because passing `self` by value guarantees that no other threads are
72    /// concurrently accessing the atomic data.
73    ///
74    /// # Examples
75    ///
76    /// ```
77    /// use crossbeam_utils::atomic::AtomicCell;
78    ///
79    /// let a = AtomicCell::new(7);
80    /// let v = a.into_inner();
81    ///
82    /// assert_eq!(v, 7);
83    /// ```
84    pub const fn into_inner(self) -> T {
85        // HACK: This is equivalent to transmute_copy by value, but available in const
86        // context even on older rustc (const transmute_copy requires Rust 1.74), and
87        // can work around "cannot borrow here, since the borrowed element may contain
88        // interior mutability" error occurs (until const_refs_to_cell stabilized, i.e.,
89        // Rust 1.83) when using transmute_copy with generic type in const context
90        // (because this is a by-value transmutation that doesn't create a reference to
91        // the source value).
92        /// # Safety
93        ///
94        /// This function has the same safety requirements as [`core::mem::transmute_copy`].
95        ///
96        /// Since this is a by-value transmutation, it copies the bits from the source value
97        /// into the destination value, then forgets the original, as with the [`core::mem::transmute`].
98        #[inline]
99        #[must_use]
100        const unsafe fn transmute_copy_by_val<Src, Dst>(src: Src) -> Dst {
101            #[repr(C)]
102            union ConstHack<Src, Dst> {
103                src: ManuallyDrop<Src>,
104                dst: ManuallyDrop<Dst>,
105            }
106            assert!(mem::size_of::<Src>() >= mem::size_of::<Dst>()); // assertion copied from transmute_copy
107            // SAFETY: ConstHack is #[repr(C)] union, and the caller must guarantee that
108            // transmuting Src to Dst is safe.
109            ManuallyDrop::into_inner(
110                ConstHack::<Src, Dst> {
111                    src: ManuallyDrop::new(src),
112                }
113                .dst,
114            )
115        }
116
117        // SAFETY:
118        // - Self is repr(transparent) over `UnsafeCell<MaybeUninit<T>>` and
119        //   `UnsafeCell<MaybeUninit<T>>` and `T` has the same layout.
120        // - passing `self` by value guarantees that no other threads are concurrently
121        //   accessing the atomic data
122        // (Equivalent to UnsafeCell::into_inner which is unstable in const context.)
123        unsafe { transmute_copy_by_val(self) }
124    }
125
126    /// Returns `true` if operations on values of this type are lock-free.
127    ///
128    /// If the compiler or the platform doesn't support the necessary atomic instructions,
129    /// `AtomicCell<T>` will use global locks for every potentially concurrent atomic operation.
130    ///
131    /// # Examples
132    ///
133    /// ```
134    /// use crossbeam_utils::atomic::AtomicCell;
135    ///
136    /// // This type is internally represented as `AtomicUsize` so we can just use atomic
137    /// // operations provided by it.
138    /// assert_eq!(AtomicCell::<usize>::is_lock_free(), true);
139    ///
140    /// // A wrapper struct around `isize`.
141    /// struct Foo {
142    ///     bar: isize,
143    /// }
144    /// // `AtomicCell<Foo>` will be internally represented as `AtomicIsize`.
145    /// assert_eq!(AtomicCell::<Foo>::is_lock_free(), true);
146    ///
147    /// // Operations on zero-sized types are always lock-free.
148    /// assert_eq!(AtomicCell::<()>::is_lock_free(), true);
149    ///
150    /// // Very large types cannot be represented as any of the standard atomic types, so atomic
151    /// // operations on them will have to use global locks for synchronization.
152    /// assert_eq!(AtomicCell::<[u8; 1000]>::is_lock_free(), false);
153    /// ```
154    pub const fn is_lock_free() -> bool {
155        atomic_is_lock_free::<T>()
156    }
157
158    /// Stores `val` into the atomic cell.
159    ///
160    /// # Examples
161    ///
162    /// ```
163    /// use crossbeam_utils::atomic::AtomicCell;
164    ///
165    /// let a = AtomicCell::new(7);
166    ///
167    /// assert_eq!(a.load(), 7);
168    /// a.store(8);
169    /// assert_eq!(a.load(), 8);
170    /// ```
171    pub fn store(&self, val: T) {
172        if mem::needs_drop::<T>() {
173            drop(self.swap(val));
174        } else {
175            unsafe {
176                atomic_store(self.as_ptr(), val);
177            }
178        }
179    }
180
181    /// Stores `val` into the atomic cell and returns the previous value.
182    ///
183    /// # Examples
184    ///
185    /// ```
186    /// use crossbeam_utils::atomic::AtomicCell;
187    ///
188    /// let a = AtomicCell::new(7);
189    ///
190    /// assert_eq!(a.load(), 7);
191    /// assert_eq!(a.swap(8), 7);
192    /// assert_eq!(a.load(), 8);
193    /// ```
194    pub fn swap(&self, val: T) -> T {
195        unsafe { atomic_swap(self.as_ptr(), val) }
196    }
197
198    /// Returns a raw pointer to the underlying data in this atomic cell.
199    ///
200    /// # Examples
201    ///
202    /// ```
203    /// use crossbeam_utils::atomic::AtomicCell;
204    ///
205    /// let a = AtomicCell::new(5);
206    ///
207    /// let ptr = a.as_ptr();
208    /// ```
209    #[inline]
210    pub const fn as_ptr(&self) -> *mut T {
211        self.value.get().cast::<T>()
212    }
213}
214
215impl<T: Default> AtomicCell<T> {
216    /// Takes the value of the atomic cell, leaving `Default::default()` in its place.
217    ///
218    /// # Examples
219    ///
220    /// ```
221    /// use crossbeam_utils::atomic::AtomicCell;
222    ///
223    /// let a = AtomicCell::new(5);
224    /// let five = a.take();
225    ///
226    /// assert_eq!(five, 5);
227    /// assert_eq!(a.into_inner(), 0);
228    /// ```
229    pub fn take(&self) -> T {
230        self.swap(Default::default())
231    }
232}
233
234impl<T: Copy> AtomicCell<T> {
235    /// Loads a value from the atomic cell.
236    ///
237    /// # Examples
238    ///
239    /// ```
240    /// use crossbeam_utils::atomic::AtomicCell;
241    ///
242    /// let a = AtomicCell::new(7);
243    ///
244    /// assert_eq!(a.load(), 7);
245    /// ```
246    pub fn load(&self) -> T {
247        unsafe { atomic_load(self.as_ptr()) }
248    }
249}
250
251impl<T: Copy + Eq> AtomicCell<T> {
252    /// If the current value equals `current`, stores `new` into the atomic cell.
253    ///
254    /// The return value is always the previous value. If it is equal to `current`, then the value
255    /// was updated.
256    ///
257    /// # Examples
258    ///
259    /// ```
260    /// # #![allow(deprecated)]
261    /// use crossbeam_utils::atomic::AtomicCell;
262    ///
263    /// let a = AtomicCell::new(1);
264    ///
265    /// assert_eq!(a.compare_and_swap(2, 3), 1);
266    /// assert_eq!(a.load(), 1);
267    ///
268    /// assert_eq!(a.compare_and_swap(1, 2), 1);
269    /// assert_eq!(a.load(), 2);
270    /// ```
271    // TODO: remove in the next major version.
272    #[deprecated(note = "Use `compare_exchange` instead")]
273    pub fn compare_and_swap(&self, current: T, new: T) -> T {
274        match self.compare_exchange(current, new) {
275            Ok(v) => v,
276            Err(v) => v,
277        }
278    }
279
280    /// If the current value equals `current`, stores `new` into the atomic cell.
281    ///
282    /// The return value is a result indicating whether the new value was written and containing
283    /// the previous value. On success this value is guaranteed to be equal to `current`.
284    ///
285    /// # Examples
286    ///
287    /// ```
288    /// use crossbeam_utils::atomic::AtomicCell;
289    ///
290    /// let a = AtomicCell::new(1);
291    ///
292    /// assert_eq!(a.compare_exchange(2, 3), Err(1));
293    /// assert_eq!(a.load(), 1);
294    ///
295    /// assert_eq!(a.compare_exchange(1, 2), Ok(1));
296    /// assert_eq!(a.load(), 2);
297    /// ```
298    pub fn compare_exchange(&self, current: T, new: T) -> Result<T, T> {
299        unsafe { atomic_compare_exchange_weak(self.as_ptr(), current, new) }
300    }
301
302    /// Fetches the value, and applies a function to it that returns an optional
303    /// new value. Returns a `Result` of `Ok(previous_value)` if the function returned `Some(_)`, else
304    /// `Err(previous_value)`.
305    ///
306    /// Note: This may call the function multiple times if the value has been changed from other threads in
307    /// the meantime, as long as the function returns `Some(_)`, but the function will have been applied
308    /// only once to the stored value.
309    ///
310    /// # Examples
311    ///
312    /// ```rust
313    /// use crossbeam_utils::atomic::AtomicCell;
314    ///
315    /// let a = AtomicCell::new(7);
316    /// assert_eq!(a.fetch_update(|_| None), Err(7));
317    /// assert_eq!(a.fetch_update(|a| Some(a + 1)), Ok(7));
318    /// assert_eq!(a.fetch_update(|a| Some(a + 1)), Ok(8));
319    /// assert_eq!(a.load(), 9);
320    /// ```
321    #[inline]
322    pub fn fetch_update<F>(&self, mut f: F) -> Result<T, T>
323    where
324        F: FnMut(T) -> Option<T>,
325    {
326        let mut prev = self.load();
327        while let Some(next) = f(prev) {
328            match self.compare_exchange(prev, next) {
329                x @ Ok(_) => return x,
330                Err(next_prev) => prev = next_prev,
331            }
332        }
333        Err(prev)
334    }
335}
336
337// `MaybeUninit` prevents `T` from being dropped, so we need to implement `Drop`
338// for `AtomicCell` to avoid leaks of non-`Copy` types.
339impl<T> Drop for AtomicCell<T> {
340    fn drop(&mut self) {
341        if mem::needs_drop::<T>() {
342            // SAFETY:
343            // - the mutable reference guarantees that no other threads are concurrently accessing the atomic data
344            // - the raw pointer passed in is valid because we got it from a reference
345            // - `MaybeUninit` prevents double dropping `T`
346            unsafe {
347                self.as_ptr().drop_in_place();
348            }
349        }
350    }
351}
352
353macro_rules! atomic {
354    // If values of type `$t` can be transmuted into values of the primitive atomic type `$atomic`,
355    // declares variable `$a` of type `$atomic` and executes `$atomic_op`, breaking out of the loop.
356    (@check, $t:ty, $atomic:ty, $a:ident, $atomic_op:expr) => {
357        if can_transmute::<$t, $atomic>() {
358            let $a: &$atomic;
359            break $atomic_op;
360        }
361    };
362
363    // If values of type `$t` can be transmuted into values of a primitive atomic type, declares
364    // variable `$a` of that type and executes `$atomic_op`. Otherwise, just executes
365    // `$fallback_op`.
366    ($t:ty, $a:ident, $atomic_op:expr, $fallback_op:expr) => {
367        loop {
368            atomic!(@check, $t, AtomicUnit, $a, $atomic_op);
369
370            atomic!(@check, $t, atomic::AtomicU8, $a, $atomic_op);
371            atomic!(@check, $t, atomic::AtomicU16, $a, $atomic_op);
372            atomic!(@check, $t, atomic::AtomicU32, $a, $atomic_op);
373            #[cfg(target_has_atomic = "64")]
374            atomic!(@check, $t, atomic::AtomicU64, $a, $atomic_op);
375            // TODO: AtomicU128 is unstable
376            // atomic!(@check, $t, atomic::AtomicU128, $a, $atomic_op);
377
378            break $fallback_op;
379        }
380    };
381}
382
383macro_rules! impl_arithmetic {
384    ($t:ty, fallback, $example:tt) => {
385        impl AtomicCell<$t> {
386            /// Increments the current value by `val` and returns the previous value.
387            ///
388            /// The addition wraps on overflow.
389            ///
390            /// # Examples
391            ///
392            /// ```
393            /// use crossbeam_utils::atomic::AtomicCell;
394            ///
395            #[doc = $example]
396            ///
397            /// assert_eq!(a.fetch_add(3), 7);
398            /// assert_eq!(a.load(), 10);
399            /// ```
400            #[inline]
401            pub fn fetch_add(&self, val: $t) -> $t {
402                let _guard = lock(self.as_ptr() as usize).write();
403                let value = unsafe { &mut *(self.as_ptr()) };
404                let old = *value;
405                *value = value.wrapping_add(val);
406                old
407            }
408
409            /// Decrements the current value by `val` and returns the previous value.
410            ///
411            /// The subtraction wraps on overflow.
412            ///
413            /// # Examples
414            ///
415            /// ```
416            /// use crossbeam_utils::atomic::AtomicCell;
417            ///
418            #[doc = $example]
419            ///
420            /// assert_eq!(a.fetch_sub(3), 7);
421            /// assert_eq!(a.load(), 4);
422            /// ```
423            #[inline]
424            pub fn fetch_sub(&self, val: $t) -> $t {
425                let _guard = lock(self.as_ptr() as usize).write();
426                let value = unsafe { &mut *(self.as_ptr()) };
427                let old = *value;
428                *value = value.wrapping_sub(val);
429                old
430            }
431
432            /// Applies bitwise "and" to the current value and returns the previous value.
433            ///
434            /// # Examples
435            ///
436            /// ```
437            /// use crossbeam_utils::atomic::AtomicCell;
438            ///
439            #[doc = $example]
440            ///
441            /// assert_eq!(a.fetch_and(3), 7);
442            /// assert_eq!(a.load(), 3);
443            /// ```
444            #[inline]
445            pub fn fetch_and(&self, val: $t) -> $t {
446                let _guard = lock(self.as_ptr() as usize).write();
447                let value = unsafe { &mut *(self.as_ptr()) };
448                let old = *value;
449                *value &= val;
450                old
451            }
452
453            /// Applies bitwise "nand" to the current value and returns the previous value.
454            ///
455            /// # Examples
456            ///
457            /// ```
458            /// use crossbeam_utils::atomic::AtomicCell;
459            ///
460            #[doc = $example]
461            ///
462            /// assert_eq!(a.fetch_nand(3), 7);
463            /// assert_eq!(a.load(), !(7 & 3));
464            /// ```
465            #[inline]
466            pub fn fetch_nand(&self, val: $t) -> $t {
467                let _guard = lock(self.as_ptr() as usize).write();
468                let value = unsafe { &mut *(self.as_ptr()) };
469                let old = *value;
470                *value = !(old & val);
471                old
472            }
473
474            /// Applies bitwise "or" to the current value and returns the previous value.
475            ///
476            /// # Examples
477            ///
478            /// ```
479            /// use crossbeam_utils::atomic::AtomicCell;
480            ///
481            #[doc = $example]
482            ///
483            /// assert_eq!(a.fetch_or(16), 7);
484            /// assert_eq!(a.load(), 23);
485            /// ```
486            #[inline]
487            pub fn fetch_or(&self, val: $t) -> $t {
488                let _guard = lock(self.as_ptr() as usize).write();
489                let value = unsafe { &mut *(self.as_ptr()) };
490                let old = *value;
491                *value |= val;
492                old
493            }
494
495            /// Applies bitwise "xor" to the current value and returns the previous value.
496            ///
497            /// # Examples
498            ///
499            /// ```
500            /// use crossbeam_utils::atomic::AtomicCell;
501            ///
502            #[doc = $example]
503            ///
504            /// assert_eq!(a.fetch_xor(2), 7);
505            /// assert_eq!(a.load(), 5);
506            /// ```
507            #[inline]
508            pub fn fetch_xor(&self, val: $t) -> $t {
509                let _guard = lock(self.as_ptr() as usize).write();
510                let value = unsafe { &mut *(self.as_ptr()) };
511                let old = *value;
512                *value ^= val;
513                old
514            }
515
516            /// Compares and sets the maximum of the current value and `val`,
517            /// and returns the previous value.
518            ///
519            /// # Examples
520            ///
521            /// ```
522            /// use crossbeam_utils::atomic::AtomicCell;
523            ///
524            #[doc = $example]
525            ///
526            /// assert_eq!(a.fetch_max(2), 7);
527            /// assert_eq!(a.load(), 7);
528            /// ```
529            #[inline]
530            pub fn fetch_max(&self, val: $t) -> $t {
531                let _guard = lock(self.as_ptr() as usize).write();
532                let value = unsafe { &mut *(self.as_ptr()) };
533                let old = *value;
534                *value = cmp::max(old, val);
535                old
536            }
537
538            /// Compares and sets the minimum of the current value and `val`,
539            /// and returns the previous value.
540            ///
541            /// # Examples
542            ///
543            /// ```
544            /// use crossbeam_utils::atomic::AtomicCell;
545            ///
546            #[doc = $example]
547            ///
548            /// assert_eq!(a.fetch_min(2), 7);
549            /// assert_eq!(a.load(), 2);
550            /// ```
551            #[inline]
552            pub fn fetch_min(&self, val: $t) -> $t {
553                let _guard = lock(self.as_ptr() as usize).write();
554                let value = unsafe { &mut *(self.as_ptr()) };
555                let old = *value;
556                *value = cmp::min(old, val);
557                old
558            }
559        }
560    };
561    ($t:ty, $atomic:ident, $example:tt) => {
562        impl AtomicCell<$t> {
563            /// Increments the current value by `val` and returns the previous value.
564            ///
565            /// The addition wraps on overflow.
566            ///
567            /// # Examples
568            ///
569            /// ```
570            /// use crossbeam_utils::atomic::AtomicCell;
571            ///
572            #[doc = $example]
573            ///
574            /// assert_eq!(a.fetch_add(3), 7);
575            /// assert_eq!(a.load(), 10);
576            /// ```
577            #[inline]
578            pub fn fetch_add(&self, val: $t) -> $t {
579                atomic! {
580                    $t, _a,
581                    {
582                        let a = unsafe { &*(self.as_ptr() as *const atomic::$atomic) };
583                        a.fetch_add(val, Ordering::AcqRel)
584                    },
585                    {
586                        let _guard = lock(self.as_ptr() as usize).write();
587                        let value = unsafe { &mut *(self.as_ptr()) };
588                        let old = *value;
589                        *value = value.wrapping_add(val);
590                        old
591                    }
592                }
593            }
594
595            /// Decrements the current value by `val` and returns the previous value.
596            ///
597            /// The subtraction wraps on overflow.
598            ///
599            /// # Examples
600            ///
601            /// ```
602            /// use crossbeam_utils::atomic::AtomicCell;
603            ///
604            #[doc = $example]
605            ///
606            /// assert_eq!(a.fetch_sub(3), 7);
607            /// assert_eq!(a.load(), 4);
608            /// ```
609            #[inline]
610            pub fn fetch_sub(&self, val: $t) -> $t {
611                atomic! {
612                    $t, _a,
613                    {
614                        let a = unsafe { &*(self.as_ptr() as *const atomic::$atomic) };
615                        a.fetch_sub(val, Ordering::AcqRel)
616                    },
617                    {
618                        let _guard = lock(self.as_ptr() as usize).write();
619                        let value = unsafe { &mut *(self.as_ptr()) };
620                        let old = *value;
621                        *value = value.wrapping_sub(val);
622                        old
623                    }
624                }
625            }
626
627            /// Applies bitwise "and" to the current value and returns the previous value.
628            ///
629            /// # Examples
630            ///
631            /// ```
632            /// use crossbeam_utils::atomic::AtomicCell;
633            ///
634            #[doc = $example]
635            ///
636            /// assert_eq!(a.fetch_and(3), 7);
637            /// assert_eq!(a.load(), 3);
638            /// ```
639            #[inline]
640            pub fn fetch_and(&self, val: $t) -> $t {
641                atomic! {
642                    $t, _a,
643                    {
644                        let a = unsafe { &*(self.as_ptr() as *const atomic::$atomic) };
645                        a.fetch_and(val, Ordering::AcqRel)
646                    },
647                    {
648                        let _guard = lock(self.as_ptr() as usize).write();
649                        let value = unsafe { &mut *(self.as_ptr()) };
650                        let old = *value;
651                        *value &= val;
652                        old
653                    }
654                }
655            }
656
657            /// Applies bitwise "nand" to the current value and returns the previous value.
658            ///
659            /// # Examples
660            ///
661            /// ```
662            /// use crossbeam_utils::atomic::AtomicCell;
663            ///
664            #[doc = $example]
665            ///
666            /// assert_eq!(a.fetch_nand(3), 7);
667            /// assert_eq!(a.load(), !(7 & 3));
668            /// ```
669            #[inline]
670            pub fn fetch_nand(&self, val: $t) -> $t {
671                atomic! {
672                    $t, _a,
673                    {
674                        let a = unsafe { &*(self.as_ptr() as *const atomic::$atomic) };
675                        a.fetch_nand(val, Ordering::AcqRel)
676                    },
677                    {
678                        let _guard = lock(self.as_ptr() as usize).write();
679                        let value = unsafe { &mut *(self.as_ptr()) };
680                        let old = *value;
681                        *value = !(old & val);
682                        old
683                    }
684                }
685            }
686
687            /// Applies bitwise "or" to the current value and returns the previous value.
688            ///
689            /// # Examples
690            ///
691            /// ```
692            /// use crossbeam_utils::atomic::AtomicCell;
693            ///
694            #[doc = $example]
695            ///
696            /// assert_eq!(a.fetch_or(16), 7);
697            /// assert_eq!(a.load(), 23);
698            /// ```
699            #[inline]
700            pub fn fetch_or(&self, val: $t) -> $t {
701                atomic! {
702                    $t, _a,
703                    {
704                        let a = unsafe { &*(self.as_ptr() as *const atomic::$atomic) };
705                        a.fetch_or(val, Ordering::AcqRel)
706                    },
707                    {
708                        let _guard = lock(self.as_ptr() as usize).write();
709                        let value = unsafe { &mut *(self.as_ptr()) };
710                        let old = *value;
711                        *value |= val;
712                        old
713                    }
714                }
715            }
716
717            /// Applies bitwise "xor" to the current value and returns the previous value.
718            ///
719            /// # Examples
720            ///
721            /// ```
722            /// use crossbeam_utils::atomic::AtomicCell;
723            ///
724            #[doc = $example]
725            ///
726            /// assert_eq!(a.fetch_xor(2), 7);
727            /// assert_eq!(a.load(), 5);
728            /// ```
729            #[inline]
730            pub fn fetch_xor(&self, val: $t) -> $t {
731                atomic! {
732                    $t, _a,
733                    {
734                        let a = unsafe { &*(self.as_ptr() as *const atomic::$atomic) };
735                        a.fetch_xor(val, Ordering::AcqRel)
736                    },
737                    {
738                        let _guard = lock(self.as_ptr() as usize).write();
739                        let value = unsafe { &mut *(self.as_ptr()) };
740                        let old = *value;
741                        *value ^= val;
742                        old
743                    }
744                }
745            }
746
747            /// Compares and sets the maximum of the current value and `val`,
748            /// and returns the previous value.
749            ///
750            /// # Examples
751            ///
752            /// ```
753            /// use crossbeam_utils::atomic::AtomicCell;
754            ///
755            #[doc = $example]
756            ///
757            /// assert_eq!(a.fetch_max(9), 7);
758            /// assert_eq!(a.load(), 9);
759            /// ```
760            #[inline]
761            pub fn fetch_max(&self, val: $t) -> $t {
762                atomic! {
763                    $t, _a,
764                    {
765                        let a = unsafe { &*(self.as_ptr() as *const atomic::$atomic) };
766                        a.fetch_max(val, Ordering::AcqRel)
767                    },
768                    {
769                        let _guard = lock(self.as_ptr() as usize).write();
770                        let value = unsafe { &mut *(self.as_ptr()) };
771                        let old = *value;
772                        *value = cmp::max(old, val);
773                        old
774                    }
775                }
776            }
777
778            /// Compares and sets the minimum of the current value and `val`,
779            /// and returns the previous value.
780            ///
781            /// # Examples
782            ///
783            /// ```
784            /// use crossbeam_utils::atomic::AtomicCell;
785            ///
786            #[doc = $example]
787            ///
788            /// assert_eq!(a.fetch_min(2), 7);
789            /// assert_eq!(a.load(), 2);
790            /// ```
791            #[inline]
792            pub fn fetch_min(&self, val: $t) -> $t {
793                atomic! {
794                    $t, _a,
795                    {
796                        let a = unsafe { &*(self.as_ptr() as *const atomic::$atomic) };
797                        a.fetch_min(val, Ordering::AcqRel)
798                    },
799                    {
800                        let _guard = lock(self.as_ptr() as usize).write();
801                        let value = unsafe { &mut *(self.as_ptr()) };
802                        let old = *value;
803                        *value = cmp::min(old, val);
804                        old
805                    }
806                }
807            }
808        }
809    };
810}
811
812impl_arithmetic!(u8, AtomicU8, "let a = AtomicCell::new(7u8);");
813impl_arithmetic!(i8, AtomicI8, "let a = AtomicCell::new(7i8);");
814impl_arithmetic!(u16, AtomicU16, "let a = AtomicCell::new(7u16);");
815impl_arithmetic!(i16, AtomicI16, "let a = AtomicCell::new(7i16);");
816
817impl_arithmetic!(u32, AtomicU32, "let a = AtomicCell::new(7u32);");
818impl_arithmetic!(i32, AtomicI32, "let a = AtomicCell::new(7i32);");
819
820#[cfg(target_has_atomic = "64")]
821impl_arithmetic!(u64, AtomicU64, "let a = AtomicCell::new(7u64);");
822#[cfg(target_has_atomic = "64")]
823impl_arithmetic!(i64, AtomicI64, "let a = AtomicCell::new(7i64);");
824#[cfg(not(target_has_atomic = "64"))]
825impl_arithmetic!(u64, fallback, "let a = AtomicCell::new(7u64);");
826#[cfg(not(target_has_atomic = "64"))]
827impl_arithmetic!(i64, fallback, "let a = AtomicCell::new(7i64);");
828
829// TODO: AtomicU128 is unstable
830// impl_arithmetic!(u128, AtomicU128, "let a = AtomicCell::new(7u128);");
831// impl_arithmetic!(i128, AtomicI128, "let a = AtomicCell::new(7i128);");
832impl_arithmetic!(u128, fallback, "let a = AtomicCell::new(7u128);");
833impl_arithmetic!(i128, fallback, "let a = AtomicCell::new(7i128);");
834
835impl_arithmetic!(usize, AtomicUsize, "let a = AtomicCell::new(7usize);");
836impl_arithmetic!(isize, AtomicIsize, "let a = AtomicCell::new(7isize);");
837
838impl AtomicCell<bool> {
839    /// Applies logical "and" to the current value and returns the previous value.
840    ///
841    /// # Examples
842    ///
843    /// ```
844    /// use crossbeam_utils::atomic::AtomicCell;
845    ///
846    /// let a = AtomicCell::new(true);
847    ///
848    /// assert_eq!(a.fetch_and(true), true);
849    /// assert_eq!(a.load(), true);
850    ///
851    /// assert_eq!(a.fetch_and(false), true);
852    /// assert_eq!(a.load(), false);
853    /// ```
854    #[inline]
855    pub fn fetch_and(&self, val: bool) -> bool {
856        atomic! {
857            bool, _a,
858            {
859                let a = unsafe { &*(self.as_ptr() as *const atomic::AtomicBool) };
860                a.fetch_and(val, Ordering::AcqRel)
861            },
862            {
863                let _guard = lock(self.as_ptr() as usize).write();
864                let value = unsafe { &mut *(self.as_ptr()) };
865                let old = *value;
866                *value &= val;
867                old
868            }
869        }
870    }
871
872    /// Applies logical "nand" to the current value and returns the previous value.
873    ///
874    /// # Examples
875    ///
876    /// ```
877    /// use crossbeam_utils::atomic::AtomicCell;
878    ///
879    /// let a = AtomicCell::new(true);
880    ///
881    /// assert_eq!(a.fetch_nand(false), true);
882    /// assert_eq!(a.load(), true);
883    ///
884    /// assert_eq!(a.fetch_nand(true), true);
885    /// assert_eq!(a.load(), false);
886    ///
887    /// assert_eq!(a.fetch_nand(false), false);
888    /// assert_eq!(a.load(), true);
889    /// ```
890    #[inline]
891    pub fn fetch_nand(&self, val: bool) -> bool {
892        atomic! {
893            bool, _a,
894            {
895                let a = unsafe { &*(self.as_ptr() as *const atomic::AtomicBool) };
896                a.fetch_nand(val, Ordering::AcqRel)
897            },
898            {
899                let _guard = lock(self.as_ptr() as usize).write();
900                let value = unsafe { &mut *(self.as_ptr()) };
901                let old = *value;
902                *value = !(old & val);
903                old
904            }
905        }
906    }
907
908    /// Applies logical "or" to the current value and returns the previous value.
909    ///
910    /// # Examples
911    ///
912    /// ```
913    /// use crossbeam_utils::atomic::AtomicCell;
914    ///
915    /// let a = AtomicCell::new(false);
916    ///
917    /// assert_eq!(a.fetch_or(false), false);
918    /// assert_eq!(a.load(), false);
919    ///
920    /// assert_eq!(a.fetch_or(true), false);
921    /// assert_eq!(a.load(), true);
922    /// ```
923    #[inline]
924    pub fn fetch_or(&self, val: bool) -> bool {
925        atomic! {
926            bool, _a,
927            {
928                let a = unsafe { &*(self.as_ptr() as *const atomic::AtomicBool) };
929                a.fetch_or(val, Ordering::AcqRel)
930            },
931            {
932                let _guard = lock(self.as_ptr() as usize).write();
933                let value = unsafe { &mut *(self.as_ptr()) };
934                let old = *value;
935                *value |= val;
936                old
937            }
938        }
939    }
940
941    /// Applies logical "xor" to the current value and returns the previous value.
942    ///
943    /// # Examples
944    ///
945    /// ```
946    /// use crossbeam_utils::atomic::AtomicCell;
947    ///
948    /// let a = AtomicCell::new(true);
949    ///
950    /// assert_eq!(a.fetch_xor(false), true);
951    /// assert_eq!(a.load(), true);
952    ///
953    /// assert_eq!(a.fetch_xor(true), true);
954    /// assert_eq!(a.load(), false);
955    /// ```
956    #[inline]
957    pub fn fetch_xor(&self, val: bool) -> bool {
958        atomic! {
959            bool, _a,
960            {
961                let a = unsafe { &*(self.as_ptr() as *const atomic::AtomicBool) };
962                a.fetch_xor(val, Ordering::AcqRel)
963            },
964            {
965                let _guard = lock(self.as_ptr() as usize).write();
966                let value = unsafe { &mut *(self.as_ptr()) };
967                let old = *value;
968                *value ^= val;
969                old
970            }
971        }
972    }
973}
974
975impl<T: Default> Default for AtomicCell<T> {
976    fn default() -> AtomicCell<T> {
977        AtomicCell::new(T::default())
978    }
979}
980
981impl<T> From<T> for AtomicCell<T> {
982    #[inline]
983    fn from(val: T) -> AtomicCell<T> {
984        AtomicCell::new(val)
985    }
986}
987
988impl<T: Copy + fmt::Debug> fmt::Debug for AtomicCell<T> {
989    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
990        f.debug_struct("AtomicCell")
991            .field("value", &self.load())
992            .finish()
993    }
994}
995
996/// Returns `true` if values of type `A` can be transmuted into values of type `B`.
997const fn can_transmute<A, B>() -> bool {
998    // Sizes must be equal, but alignment of `A` must be greater or equal than that of `B`.
999    (mem::size_of::<A>() == mem::size_of::<B>()) & (mem::align_of::<A>() >= mem::align_of::<B>())
1000}
1001
1002/// Returns a reference to the global lock associated with the `AtomicCell` at address `addr`.
1003///
1004/// This function is used to protect atomic data which doesn't fit into any of the primitive atomic
1005/// types in `std::sync::atomic`. Operations on such atomics must therefore use a global lock.
1006///
1007/// However, there is not only one global lock but an array of many locks, and one of them is
1008/// picked based on the given address. Having many locks reduces contention and improves
1009/// scalability.
1010#[inline]
1011#[must_use]
1012fn lock(addr: usize) -> &'static SeqLock {
1013    // The number of locks is a prime number because we want to make sure `addr % LEN` gets
1014    // dispersed across all locks.
1015    //
1016    // Note that addresses are always aligned to some power of 2, depending on type `T` in
1017    // `AtomicCell<T>`. If `LEN` was an even number, then `addr % LEN` would be an even number,
1018    // too, which means only half of the locks would get utilized!
1019    //
1020    // It is also possible for addresses to accidentally get aligned to a number that is not a
1021    // power of 2. Consider this example:
1022    //
1023    // ```
1024    // #[repr(C)]
1025    // struct Foo {
1026    //     a: AtomicCell<u8>,
1027    //     b: u8,
1028    //     c: u8,
1029    // }
1030    // ```
1031    //
1032    // Now, if we have a slice of type `&[Foo]`, it is possible that field `a` in all items gets
1033    // stored at addresses that are multiples of 3. It'd be too bad if `LEN` was divisible by 3.
1034    // In order to protect from such cases, we simply choose a large prime number for `LEN`.
1035    const LEN: usize = 67;
1036    const L: CachePadded<SeqLock> = CachePadded::new(SeqLock::new());
1037    static LOCKS: [CachePadded<SeqLock>; LEN] = [L; LEN];
1038
1039    // If the modulus is a constant number, the compiler will use crazy math to transform this into
1040    // a sequence of cheap arithmetic operations rather than using the slow modulo instruction.
1041    &LOCKS[addr % LEN]
1042}
1043
1044/// An atomic `()`.
1045///
1046/// All operations are noops.
1047struct AtomicUnit;
1048
1049impl AtomicUnit {
1050    #[inline]
1051    fn load(&self, _order: Ordering) {}
1052
1053    #[inline]
1054    fn store(&self, _val: (), _order: Ordering) {}
1055
1056    #[inline]
1057    fn swap(&self, _val: (), _order: Ordering) {}
1058
1059    #[inline]
1060    fn compare_exchange_weak(
1061        &self,
1062        _current: (),
1063        _new: (),
1064        _success: Ordering,
1065        _failure: Ordering,
1066    ) -> Result<(), ()> {
1067        Ok(())
1068    }
1069}
1070
1071/// Returns `true` if operations on `AtomicCell<T>` are lock-free.
1072const fn atomic_is_lock_free<T>() -> bool {
1073    atomic! { T, _a, true, false }
1074}
1075
1076/// Atomically reads data from `src`.
1077///
1078/// This operation uses the `Acquire` ordering. If possible, an atomic instructions is used, and a
1079/// global lock otherwise.
1080unsafe fn atomic_load<T>(src: *mut T) -> T
1081where
1082    T: Copy,
1083{
1084    atomic! {
1085        T, a,
1086        {
1087            a = &*(src as *const _ as *const _);
1088            mem::transmute_copy(&a.load(Ordering::Acquire))
1089        },
1090        {
1091            let lock = lock(src as usize);
1092
1093            // Try doing an optimistic read first.
1094            if let Some(stamp) = lock.optimistic_read() {
1095                // We need a volatile read here because other threads might concurrently modify the
1096                // value. In theory, data races are *always* UB, even if we use volatile reads and
1097                // discard the data when a data race is detected. The proper solution would be to
1098                // do atomic reads and atomic writes, but we can't atomically read and write all
1099                // kinds of data since `AtomicU8` is not available on stable Rust yet.
1100                // Load as `MaybeUninit` because we may load a value that is not valid as `T`.
1101                let val = ptr::read_volatile(src.cast::<MaybeUninit<T>>());
1102
1103                if lock.validate_read(stamp) {
1104                    return val.assume_init();
1105                }
1106            }
1107
1108            // Grab a regular write lock so that writers don't starve this load.
1109            let guard = lock.write();
1110            let val = ptr::read(src);
1111            // The value hasn't been changed. Drop the guard without incrementing the stamp.
1112            guard.abort();
1113            val
1114        }
1115    }
1116}
1117
1118/// Atomically writes `val` to `dst`.
1119///
1120/// This operation uses the `Release` ordering. If possible, an atomic instructions is used, and a
1121/// global lock otherwise.
1122unsafe fn atomic_store<T>(dst: *mut T, val: T) {
1123    atomic! {
1124        T, a,
1125        {
1126            a = &*(dst as *const _ as *const _);
1127            a.store(mem::transmute_copy(&val), Ordering::Release);
1128            mem::forget(val);
1129        },
1130        {
1131            let _guard = lock(dst as usize).write();
1132            ptr::write(dst, val);
1133        }
1134    }
1135}
1136
1137/// Atomically swaps data at `dst` with `val`.
1138///
1139/// This operation uses the `AcqRel` ordering. If possible, an atomic instructions is used, and a
1140/// global lock otherwise.
1141unsafe fn atomic_swap<T>(dst: *mut T, val: T) -> T {
1142    atomic! {
1143        T, a,
1144        {
1145            a = &*(dst as *const _ as *const _);
1146            let res = mem::transmute_copy(&a.swap(mem::transmute_copy(&val), Ordering::AcqRel));
1147            mem::forget(val);
1148            res
1149        },
1150        {
1151            let _guard = lock(dst as usize).write();
1152            ptr::replace(dst, val)
1153        }
1154    }
1155}
1156
1157/// Atomically compares data at `dst` to `current` and, if equal byte-for-byte, exchanges data at
1158/// `dst` with `new`.
1159///
1160/// Returns the old value on success, or the current value at `dst` on failure.
1161///
1162/// This operation uses the `AcqRel` ordering. If possible, an atomic instructions is used, and a
1163/// global lock otherwise.
1164#[allow(clippy::let_unit_value)]
1165unsafe fn atomic_compare_exchange_weak<T>(dst: *mut T, mut current: T, new: T) -> Result<T, T>
1166where
1167    T: Copy + Eq,
1168{
1169    atomic! {
1170        T, a,
1171        {
1172            a = &*(dst as *const _ as *const _);
1173            let mut current_raw = mem::transmute_copy(&current);
1174            let new_raw = mem::transmute_copy(&new);
1175
1176            loop {
1177                match a.compare_exchange_weak(
1178                    current_raw,
1179                    new_raw,
1180                    Ordering::AcqRel,
1181                    Ordering::Acquire,
1182                ) {
1183                    Ok(_) => break Ok(current),
1184                    Err(previous_raw) => {
1185                        let previous = mem::transmute_copy(&previous_raw);
1186
1187                        if !T::eq(&previous, &current) {
1188                            break Err(previous);
1189                        }
1190
1191                        // The compare-exchange operation has failed and didn't store `new`. The
1192                        // failure is either spurious, or `previous` was semantically equal to
1193                        // `current` but not byte-equal. Let's retry with `previous` as the new
1194                        // `current`.
1195                        current = previous;
1196                        current_raw = previous_raw;
1197                    }
1198                }
1199            }
1200        },
1201        {
1202            let guard = lock(dst as usize).write();
1203
1204            if T::eq(&*dst, &current) {
1205                Ok(ptr::replace(dst, new))
1206            } else {
1207                let val = ptr::read(dst);
1208                // The value hasn't been changed. Drop the guard without incrementing the stamp.
1209                guard.abort();
1210                Err(val)
1211            }
1212        }
1213    }
1214}