|
27 | 27 | // on another thread) using `Ordering::Release`, so we must use
|
28 | 28 | // `Ordering::Acquire` to ensure that store "happens-before" this load.
|
29 | 29 |
|
30 |
| -use core::sync::atomic; |
31 |
| - |
32 |
| -use atomic::{AtomicUsize, Ordering}; |
| 30 | +use cfg_if::cfg_if; |
| 31 | +use core::marker::PhantomData; |
33 | 32 | use core::num::NonZeroUsize;
|
| 33 | +use core::sync::atomic::{self, AtomicUsize}; |
| 34 | + |
| 35 | +pub trait Ordering { |
| 36 | + const ACQUIRE: atomic::Ordering; |
| 37 | + const RELEASE: atomic::Ordering; |
| 38 | +} |
| 39 | + |
| 40 | +cfg_if! { |
| 41 | + if #[cfg(any(all(target_arch = "arm", target_endian = "little"), |
| 42 | + target_arch = "x86", |
| 43 | + target_arch = "x86_64"))] |
| 44 | + { |
| 45 | + pub struct AcquireRelease(()); |
| 46 | + |
| 47 | + impl Ordering for AcquireRelease { |
| 48 | + const ACQUIRE: atomic::Ordering = atomic::Ordering::Acquire; |
| 49 | + const RELEASE: atomic::Ordering = atomic::Ordering::Release; |
| 50 | + } |
| 51 | + } |
| 52 | +} |
| 53 | + |
| 54 | +cfg_if! { |
| 55 | + if #[cfg(all(target_arch = "aarch64", target_endian = "little"))] { |
| 56 | + pub struct Relaxed(()); |
| 57 | + |
| 58 | + impl Ordering for Relaxed { |
| 59 | + const ACQUIRE: atomic::Ordering = atomic::Ordering::Relaxed; |
| 60 | + const RELEASE: atomic::Ordering = atomic::Ordering::Relaxed; |
| 61 | + } |
| 62 | + } |
| 63 | +} |
34 | 64 |
|
35 | 65 | /// A thread-safe cell which can be written to only once.
|
36 |
| -pub struct OnceNonZeroUsize { |
| 66 | +pub struct OnceNonZeroUsize<O> { |
37 | 67 | inner: AtomicUsize,
|
| 68 | + ordering: PhantomData<O>, |
38 | 69 | }
|
39 | 70 |
|
40 |
| -impl OnceNonZeroUsize { |
| 71 | +impl<O: Ordering> OnceNonZeroUsize<O> { |
41 | 72 | /// Creates a new empty cell.
|
42 | 73 | #[inline]
|
43 | 74 | pub const fn new() -> Self {
|
44 | 75 | Self {
|
45 | 76 | inner: AtomicUsize::new(0),
|
| 77 | + ordering: PhantomData, |
46 | 78 | }
|
47 | 79 | }
|
48 | 80 |
|
49 | 81 | /// Gets the underlying value.
|
50 | 82 | #[inline]
|
51 | 83 | pub fn get(&self) -> Option<NonZeroUsize> {
|
52 |
| - let val = self.inner.load(Ordering::Acquire); |
| 84 | + let val = self.inner.load(O::ACQUIRE); |
53 | 85 | NonZeroUsize::new(val)
|
54 | 86 | }
|
55 | 87 |
|
@@ -124,6 +156,6 @@ impl OnceNonZeroUsize {
|
124 | 156 | #[inline(always)]
|
125 | 157 | fn compare_exchange(&self, val: NonZeroUsize) -> Result<usize, usize> {
|
126 | 158 | self.inner
|
127 |
| - .compare_exchange(0, val.get(), Ordering::Release, Ordering::Acquire) |
| 159 | + .compare_exchange(0, val.get(), O::RELEASE, O::ACQUIRE) |
128 | 160 | }
|
129 | 161 | }
|
0 commit comments