diff --git a/src/lib.rs b/src/lib.rs index 1f89ca6..7e47aa2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -74,7 +74,7 @@ unsafe impl Sync for Atomic {} impl RefUnwindSafe for Atomic {} impl Default for Atomic { - #[inline] + #[inline(always)] fn default() -> Self { Self::new(Default::default()) } @@ -90,9 +90,9 @@ impl fmt::Debug for Atomic { impl Atomic { /// Creates a new `Atomic`. - #[inline] - pub const fn new(v: T) -> Atomic { - Atomic { + #[inline(always)] + pub const fn new(v: T) -> Self { + Self { v: UnsafeCell::new(MaybeUninit::new(v)), } } @@ -102,15 +102,18 @@ impl Atomic { /// If an `Atomic` is not lock-free then it may be implemented using locks /// internally, which makes it unsuitable for some situations (such as /// communicating with a signal handler). - #[inline] + #[inline(always)] pub const fn is_lock_free() -> bool { ops::atomic_is_lock_free::() } } impl Atomic { - #[inline] - fn inner_ptr(&self) -> *mut T { + /// Returns a mutable pointer to the underlying type. + /// + + #[inline(always)] + pub fn as_ptr(&self) -> *mut T { self.v.get() as *mut T } @@ -118,16 +121,16 @@ impl Atomic { /// /// This is safe because the mutable reference guarantees that no other threads are /// concurrently accessing the atomic data. - #[inline] + #[inline(always)] pub fn get_mut(&mut self) -> &mut T { - unsafe { &mut *self.inner_ptr() } + unsafe { &mut *self.as_ptr() } } /// Consumes the atomic and returns the contained value. /// /// This is safe because passing `self` by value guarantees that no other threads are /// concurrently accessing the atomic data. - #[inline] + #[inline(always)] pub fn into_inner(self) -> T { unsafe { self.v.into_inner().assume_init() } } @@ -140,9 +143,9 @@ impl Atomic { /// # Panics /// /// Panics if `order` is `Release` or `AcqRel`. - #[inline] + #[inline(always)] pub fn load(&self, order: Ordering) -> T { - unsafe { ops::atomic_load(self.inner_ptr(), order) } + unsafe { ops::atomic_load(self.as_ptr(), order) } } /// Stores a value into the `Atomic`. @@ -153,10 +156,10 @@ impl Atomic { /// # Panics /// /// Panics if `order` is `Acquire` or `AcqRel`. - #[inline] + #[inline(always)] pub fn store(&self, val: T, order: Ordering) { unsafe { - ops::atomic_store(self.inner_ptr(), val, order); + ops::atomic_store(self.as_ptr(), val, order); } } @@ -164,9 +167,9 @@ impl Atomic { /// /// `swap` takes an `Ordering` argument which describes the memory ordering /// of this operation. - #[inline] + #[inline(always)] pub fn swap(&self, val: T, order: Ordering) -> T { - unsafe { ops::atomic_swap(self.inner_ptr(), val, order) } + unsafe { ops::atomic_swap(self.as_ptr(), val, order) } } /// Stores a value into the `Atomic` if the current value is the same as the @@ -181,7 +184,7 @@ impl Atomic { /// the operation succeeds while the second describes the required ordering /// when the operation fails. The failure ordering can't be `Release` or /// `AcqRel` and must be equivalent or weaker than the success ordering. - #[inline] + #[inline(always)] pub fn compare_exchange( &self, current: T, @@ -189,7 +192,7 @@ impl Atomic { success: Ordering, failure: Ordering, ) -> Result { - unsafe { ops::atomic_compare_exchange(self.inner_ptr(), current, new, success, failure) } + unsafe { ops::atomic_compare_exchange(self.as_ptr(), current, new, success, failure) } } /// Stores a value into the `Atomic` if the current value is the same as the @@ -206,7 +209,7 @@ impl Atomic { /// when the operation fails. The failure ordering can't be `Release` or /// `AcqRel` and must be equivalent or weaker than the success ordering. /// success ordering. - #[inline] + #[inline(always)] pub fn compare_exchange_weak( &self, current: T, @@ -214,9 +217,7 @@ impl Atomic { success: Ordering, failure: Ordering, ) -> Result { - unsafe { - ops::atomic_compare_exchange_weak(self.inner_ptr(), current, new, success, failure) - } + unsafe { ops::atomic_compare_exchange_weak(self.as_ptr(), current, new, success, failure) } } /// Fetches the value, and applies a function to it that returns an optional @@ -255,7 +256,7 @@ impl Atomic { /// assert_eq!(x.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |x| Some(x + 1)), Ok(8)); /// assert_eq!(x.load(Ordering::SeqCst), 9); /// ``` - #[inline] + #[inline(always)] pub fn fetch_update( &self, set_order: Ordering, @@ -283,9 +284,9 @@ impl Atomic { /// `val`, and sets the new value to the result. /// /// Returns the previous value. - #[inline] + #[inline(always)] pub fn fetch_and(&self, val: bool, order: Ordering) -> bool { - unsafe { ops::atomic_and(self.inner_ptr(), val, order) } + unsafe { ops::atomic_and(self.as_ptr(), val, order) } } /// Logical "or" with a boolean value. @@ -294,9 +295,9 @@ impl Atomic { /// `val`, and sets the new value to the result. /// /// Returns the previous value. - #[inline] + #[inline(always)] pub fn fetch_or(&self, val: bool, order: Ordering) -> bool { - unsafe { ops::atomic_or(self.inner_ptr(), val, order) } + unsafe { ops::atomic_or(self.as_ptr(), val, order) } } /// Logical "xor" with a boolean value. @@ -305,9 +306,9 @@ impl Atomic { /// `val`, and sets the new value to the result. /// /// Returns the previous value. - #[inline] + #[inline(always)] pub fn fetch_xor(&self, val: bool, order: Ordering) -> bool { - unsafe { ops::atomic_xor(self.inner_ptr(), val, order) } + unsafe { ops::atomic_xor(self.as_ptr(), val, order) } } } @@ -315,33 +316,33 @@ macro_rules! atomic_ops_common { ($($t:ty)*) => ($( impl Atomic<$t> { /// Add to the current value, returning the previous value. - #[inline] + #[inline(always)] pub fn fetch_add(&self, val: $t, order: Ordering) -> $t { - unsafe { ops::atomic_add(self.inner_ptr(), val, order) } + unsafe { ops::atomic_add(self.as_ptr(), val, order) } } /// Subtract from the current value, returning the previous value. - #[inline] + #[inline(always)] pub fn fetch_sub(&self, val: $t, order: Ordering) -> $t { - unsafe { ops::atomic_sub(self.inner_ptr(), val, order) } + unsafe { ops::atomic_sub(self.as_ptr(), val, order) } } /// Bitwise and with the current value, returning the previous value. - #[inline] + #[inline(always)] pub fn fetch_and(&self, val: $t, order: Ordering) -> $t { - unsafe { ops::atomic_and(self.inner_ptr(), val, order) } + unsafe { ops::atomic_and(self.as_ptr(), val, order) } } /// Bitwise or with the current value, returning the previous value. - #[inline] + #[inline(always)] pub fn fetch_or(&self, val: $t, order: Ordering) -> $t { - unsafe { ops::atomic_or(self.inner_ptr(), val, order) } + unsafe { ops::atomic_or(self.as_ptr(), val, order) } } /// Bitwise xor with the current value, returning the previous value. - #[inline] + #[inline(always)] pub fn fetch_xor(&self, val: $t, order: Ordering) -> $t { - unsafe { ops::atomic_xor(self.inner_ptr(), val, order) } + unsafe { ops::atomic_xor(self.as_ptr(), val, order) } } } )*); @@ -352,15 +353,15 @@ macro_rules! atomic_ops_signed { $( impl Atomic<$t> { /// Minimum with the current value. - #[inline] + #[inline(always)] pub fn fetch_min(&self, val: $t, order: Ordering) -> $t { - unsafe { ops::atomic_min(self.inner_ptr(), val, order) } + unsafe { ops::atomic_min(self.as_ptr(), val, order) } } /// Maximum with the current value. - #[inline] + #[inline(always)] pub fn fetch_max(&self, val: $t, order: Ordering) -> $t { - unsafe { ops::atomic_max(self.inner_ptr(), val, order) } + unsafe { ops::atomic_max(self.as_ptr(), val, order) } } } )* @@ -372,15 +373,15 @@ macro_rules! atomic_ops_unsigned { $( impl Atomic<$t> { /// Minimum with the current value. - #[inline] + #[inline(always)] pub fn fetch_min(&self, val: $t, order: Ordering) -> $t { - unsafe { ops::atomic_umin(self.inner_ptr(), val, order) } + unsafe { ops::atomic_umin(self.as_ptr(), val, order) } } /// Maximum with the current value. - #[inline] + #[inline(always)] pub fn fetch_max(&self, val: $t, order: Ordering) -> $t { - unsafe { ops::atomic_umax(self.inner_ptr(), val, order) } + unsafe { ops::atomic_umax(self.as_ptr(), val, order) } } } )*