From 79482e7e9466ece693e0104ae8f0aa8826eaf2b5 Mon Sep 17 00:00:00 2001 From: yvt Date: Fri, 10 Jul 2020 18:13:07 +0900 Subject: [PATCH] deprecate `try_lock_order`, introduce `try_lock_explicit[_unchecked]` --- src/lib.rs | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 65 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 7c0feec..6dfa484 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -82,10 +82,13 @@ impl TryLock { /// /// The default memory ordering is to use `Acquire` to lock, and `Release` /// to unlock. If different ordering is required, use - /// [`try_lock_order`](TryLock::try_lock_order). + /// [`try_lock_explicit`](TryLock::try_lock_explicit) or + /// [`try_lock_explicit_unchecked`](TryLock::try_lock_explicit_unchecked). #[inline] pub fn try_lock(&self) -> Option> { - self.try_lock_order(Ordering::Acquire, Ordering::Release) + unsafe { + self.try_lock_explicit_unchecked(Ordering::Acquire, Ordering::Release) + } } /// Try to acquire the lock of this value using the lock and unlock orderings. @@ -95,7 +98,67 @@ impl TryLock { /// by spinning a few times, or by using some other means of /// notification. #[inline] + #[deprecated( + since = "0.2.3", + note = "This method is actually unsafe because it unsafely allows \ + the use of weaker memory ordering. Please use try_lock_explicit instead" + )] pub fn try_lock_order(&self, lock_order: Ordering, unlock_order: Ordering) -> Option> { + unsafe { + self.try_lock_explicit_unchecked(lock_order, unlock_order) + } + } + + /// Try to acquire the lock of this value using the specified lock and + /// unlock orderings. + /// + /// If the lock is already acquired by someone else, this returns + /// `None`. You can try to acquire again whenever you want, perhaps + /// by spinning a few times, or by using some other means of + /// notification. + /// + /// # Panic + /// + /// This method panics if `lock_order` is not any of `Acquire`, `AcqRel`, + /// and `SeqCst`, or `unlock_order` is not any of `Release` and `SeqCst`. + #[inline] + pub fn try_lock_explicit(&self, lock_order: Ordering, unlock_order: Ordering) -> Option> { + match lock_order { + Ordering::Acquire | + Ordering::AcqRel | + Ordering::SeqCst => {} + _ => panic!("lock ordering must be `Acquire`, `AcqRel`, or `SeqCst`"), + } + + match unlock_order { + Ordering::Release | + Ordering::SeqCst => {} + _ => panic!("unlock ordering must be `Release` or `SeqCst`"), + } + + unsafe { + self.try_lock_explicit_unchecked(lock_order, unlock_order) + } + } + + /// Try to acquire the lock of this value using the specified lock and + /// unlock orderings without checking that the specified orderings are + /// strong enough to be safe. + /// + /// If the lock is already acquired by someone else, this returns + /// `None`. You can try to acquire again whenever you want, perhaps + /// by spinning a few times, or by using some other means of + /// notification. + /// + /// # Safety + /// + /// Unlike [`try_lock_explicit`], this method is unsafe because it does not + /// check that the given memory orderings are strong enough to prevent data + /// race. + /// + /// [`try_lock_explicit`]: Self::try_lock_explicit + #[inline] + pub unsafe fn try_lock_explicit_unchecked(&self, lock_order: Ordering, unlock_order: Ordering) -> Option> { if !self.is_locked.swap(true, lock_order) { Some(Locked { lock: self,