Skip to content

Commit

Permalink
Merge pull request #403 from Lochlanna/public-guard-creation
Browse files Browse the repository at this point in the history
  • Loading branch information
Amanieu authored Oct 17, 2023
2 parents b6eb569 + 3f38a9e commit 669bf52
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 68 deletions.
34 changes: 22 additions & 12 deletions lock_api/src/mutex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,11 +189,16 @@ impl<R, T> Mutex<R, T> {
}

impl<R: RawMutex, T: ?Sized> Mutex<R, T> {
/// Creates a new `MutexGuard` without checking if the mutex is locked.
///
/// # Safety
///
/// The lock must be held when calling this method.
/// This method must only be called if the thread logically holds the lock.
///
/// Calling this function when a guard has already been produced is undefined behaviour unless
/// the guard was forgotten with `mem::forget`.
#[inline]
unsafe fn guard(&self) -> MutexGuard<'_, R, T> {
pub unsafe fn make_guard_unchecked(&self) -> MutexGuard<'_, R, T> {
MutexGuard {
mutex: self,
marker: PhantomData,
Expand All @@ -213,7 +218,7 @@ impl<R: RawMutex, T: ?Sized> Mutex<R, T> {
pub fn lock(&self) -> MutexGuard<'_, R, T> {
self.raw.lock();
// SAFETY: The lock is held, as required.
unsafe { self.guard() }
unsafe { self.make_guard_unchecked() }
}

/// Attempts to acquire this lock.
Expand All @@ -227,7 +232,7 @@ impl<R: RawMutex, T: ?Sized> Mutex<R, T> {
pub fn try_lock(&self) -> Option<MutexGuard<'_, R, T>> {
if self.raw.try_lock() {
// SAFETY: The lock is held, as required.
Some(unsafe { self.guard() })
Some(unsafe { self.make_guard_unchecked() })
} else {
None
}
Expand Down Expand Up @@ -294,12 +299,17 @@ impl<R: RawMutex, T: ?Sized> Mutex<R, T> {
self.data.get()
}

/// Creates a new `ArcMutexGuard` without checking if the mutex is locked.
///
/// # Safety
///
/// The lock needs to be held for the behavior of this function to be defined.
/// This method must only be called if the thread logically holds the lock.
///
/// Calling this function when a guard has already been produced is undefined behaviour unless
/// the guard was forgotten with `mem::forget`.
#[cfg(feature = "arc_lock")]
#[inline]
unsafe fn guard_arc(self: &Arc<Self>) -> ArcMutexGuard<R, T> {
unsafe fn make_arc_guard_unchecked(self: &Arc<Self>) -> ArcMutexGuard<R, T> {
ArcMutexGuard {
mutex: self.clone(),
marker: PhantomData,
Expand All @@ -315,7 +325,7 @@ impl<R: RawMutex, T: ?Sized> Mutex<R, T> {
pub fn lock_arc(self: &Arc<Self>) -> ArcMutexGuard<R, T> {
self.raw.lock();
// SAFETY: the locking guarantee is upheld
unsafe { self.guard_arc() }
unsafe { self.make_arc_guard_unchecked() }
}

/// Attempts to acquire a lock through an `Arc`.
Expand All @@ -327,7 +337,7 @@ impl<R: RawMutex, T: ?Sized> Mutex<R, T> {
pub fn try_lock_arc(self: &Arc<Self>) -> Option<ArcMutexGuard<R, T>> {
if self.raw.try_lock() {
// SAFETY: locking guarantee is upheld
Some(unsafe { self.guard_arc() })
Some(unsafe { self.make_arc_guard_unchecked() })
} else {
None
}
Expand Down Expand Up @@ -362,7 +372,7 @@ impl<R: RawMutexTimed, T: ?Sized> Mutex<R, T> {
pub fn try_lock_for(&self, timeout: R::Duration) -> Option<MutexGuard<'_, R, T>> {
if self.raw.try_lock_for(timeout) {
// SAFETY: The lock is held, as required.
Some(unsafe { self.guard() })
Some(unsafe { self.make_guard_unchecked() })
} else {
None
}
Expand All @@ -377,7 +387,7 @@ impl<R: RawMutexTimed, T: ?Sized> Mutex<R, T> {
pub fn try_lock_until(&self, timeout: R::Instant) -> Option<MutexGuard<'_, R, T>> {
if self.raw.try_lock_until(timeout) {
// SAFETY: The lock is held, as required.
Some(unsafe { self.guard() })
Some(unsafe { self.make_guard_unchecked() })
} else {
None
}
Expand All @@ -392,7 +402,7 @@ impl<R: RawMutexTimed, T: ?Sized> Mutex<R, T> {
pub fn try_lock_arc_for(self: &Arc<Self>, timeout: R::Duration) -> Option<ArcMutexGuard<R, T>> {
if self.raw.try_lock_for(timeout) {
// SAFETY: locking guarantee is upheld
Some(unsafe { self.guard_arc() })
Some(unsafe { self.make_arc_guard_unchecked() })
} else {
None
}
Expand All @@ -410,7 +420,7 @@ impl<R: RawMutexTimed, T: ?Sized> Mutex<R, T> {
) -> Option<ArcMutexGuard<R, T>> {
if self.raw.try_lock_until(timeout) {
// SAFETY: locking guarantee is upheld
Some(unsafe { self.guard_arc() })
Some(unsafe { self.make_arc_guard_unchecked() })
} else {
None
}
Expand Down
34 changes: 22 additions & 12 deletions lock_api/src/remutex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -289,11 +289,16 @@ impl<R, G, T> ReentrantMutex<R, G, T> {
}

impl<R: RawMutex, G: GetThreadId, T: ?Sized> ReentrantMutex<R, G, T> {
/// Creates a new `ReentrantMutexGuard` without checking if the lock is held.
///
/// # Safety
///
/// The lock must be held when calling this method.
/// This method must only be called if the thread logically holds the lock.
///
/// Calling this function when a guard has already been produced is undefined behaviour unless
/// the guard was forgotten with `mem::forget`.
#[inline]
unsafe fn guard(&self) -> ReentrantMutexGuard<'_, R, G, T> {
pub unsafe fn make_guard_unchecked(&self) -> ReentrantMutexGuard<'_, R, G, T> {
ReentrantMutexGuard {
remutex: &self,
marker: PhantomData,
Expand All @@ -314,7 +319,7 @@ impl<R: RawMutex, G: GetThreadId, T: ?Sized> ReentrantMutex<R, G, T> {
pub fn lock(&self) -> ReentrantMutexGuard<'_, R, G, T> {
self.raw.lock();
// SAFETY: The lock is held, as required.
unsafe { self.guard() }
unsafe { self.make_guard_unchecked() }
}

/// Attempts to acquire this lock.
Expand All @@ -328,7 +333,7 @@ impl<R: RawMutex, G: GetThreadId, T: ?Sized> ReentrantMutex<R, G, T> {
pub fn try_lock(&self) -> Option<ReentrantMutexGuard<'_, R, G, T>> {
if self.raw.try_lock() {
// SAFETY: The lock is held, as required.
Some(unsafe { self.guard() })
Some(unsafe { self.make_guard_unchecked() })
} else {
None
}
Expand Down Expand Up @@ -402,12 +407,17 @@ impl<R: RawMutex, G: GetThreadId, T: ?Sized> ReentrantMutex<R, G, T> {
self.data.get()
}

/// Creates a new `ArcReentrantMutexGuard` without checking if the lock is held.
///
/// # Safety
///
/// The lock must be held before calling this method.
/// This method must only be called if the thread logically holds the lock.
///
/// Calling this function when a guard has already been produced is undefined behaviour unless
/// the guard was forgotten with `mem::forget`.
#[cfg(feature = "arc_lock")]
#[inline]
unsafe fn guard_arc(self: &Arc<Self>) -> ArcReentrantMutexGuard<R, G, T> {
pub unsafe fn make_arc_guard_unchecked(self: &Arc<Self>) -> ArcReentrantMutexGuard<R, G, T> {
ArcReentrantMutexGuard {
remutex: self.clone(),
marker: PhantomData,
Expand All @@ -423,7 +433,7 @@ impl<R: RawMutex, G: GetThreadId, T: ?Sized> ReentrantMutex<R, G, T> {
pub fn lock_arc(self: &Arc<Self>) -> ArcReentrantMutexGuard<R, G, T> {
self.raw.lock();
// SAFETY: locking guarantee is upheld
unsafe { self.guard_arc() }
unsafe { self.make_arc_guard_unchecked() }
}

/// Attempts to acquire a reentrant mutex through an `Arc`.
Expand All @@ -435,7 +445,7 @@ impl<R: RawMutex, G: GetThreadId, T: ?Sized> ReentrantMutex<R, G, T> {
pub fn try_lock_arc(self: &Arc<Self>) -> Option<ArcReentrantMutexGuard<R, G, T>> {
if self.raw.try_lock() {
// SAFETY: locking guarantee is upheld
Some(unsafe { self.guard_arc() })
Some(unsafe { self.make_arc_guard_unchecked() })
} else {
None
}
Expand Down Expand Up @@ -470,7 +480,7 @@ impl<R: RawMutexTimed, G: GetThreadId, T: ?Sized> ReentrantMutex<R, G, T> {
pub fn try_lock_for(&self, timeout: R::Duration) -> Option<ReentrantMutexGuard<'_, R, G, T>> {
if self.raw.try_lock_for(timeout) {
// SAFETY: The lock is held, as required.
Some(unsafe { self.guard() })
Some(unsafe { self.make_guard_unchecked() })
} else {
None
}
Expand All @@ -485,7 +495,7 @@ impl<R: RawMutexTimed, G: GetThreadId, T: ?Sized> ReentrantMutex<R, G, T> {
pub fn try_lock_until(&self, timeout: R::Instant) -> Option<ReentrantMutexGuard<'_, R, G, T>> {
if self.raw.try_lock_until(timeout) {
// SAFETY: The lock is held, as required.
Some(unsafe { self.guard() })
Some(unsafe { self.make_guard_unchecked() })
} else {
None
}
Expand All @@ -503,7 +513,7 @@ impl<R: RawMutexTimed, G: GetThreadId, T: ?Sized> ReentrantMutex<R, G, T> {
) -> Option<ArcReentrantMutexGuard<R, G, T>> {
if self.raw.try_lock_for(timeout) {
// SAFETY: locking guarantee is upheld
Some(unsafe { self.guard_arc() })
Some(unsafe { self.make_arc_guard_unchecked() })
} else {
None
}
Expand All @@ -521,7 +531,7 @@ impl<R: RawMutexTimed, G: GetThreadId, T: ?Sized> ReentrantMutex<R, G, T> {
) -> Option<ArcReentrantMutexGuard<R, G, T>> {
if self.raw.try_lock_until(timeout) {
// SAFETY: locking guarantee is upheld
Some(unsafe { self.guard_arc() })
Some(unsafe { self.make_arc_guard_unchecked() })
} else {
None
}
Expand Down
Loading

0 comments on commit 669bf52

Please sign in to comment.