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