Skip to content

Commit

Permalink
fix(maitake-sync): impl Future for mutex::Lock with generic `Scop…
Browse files Browse the repository at this point in the history
…edRawMutex` (#517)

This commit fixes the trait bounds on the `mutex::Lock` type's `Future`
implementation so that it's present when used with an overridden
`ScopedRawMutex`, as well as the default `DefaultMutex`. Thanks to
@peterkrull for reporting this issue in [this comment][1]!

As noted in #516, I've also added tests for this, which wouldn't have
compiled prior to this change.

[1]: #515 (comment)
  • Loading branch information
hawkw authored Feb 6, 2025
1 parent 509a8b7 commit 12c5b21
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 2 deletions.
8 changes: 6 additions & 2 deletions maitake-sync/src/mutex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -348,8 +348,12 @@ where

// === impl Lock ===

impl<'a, T> Future for Lock<'a, T> {
type Output = MutexGuard<'a, T>;
impl<'a, T, L> Future for Lock<'a, T, L>
where
T: ?Sized,
L: ScopedRawMutex,
{
type Output = MutexGuard<'a, T, L>;

fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let this = self.project();
Expand Down
49 changes: 49 additions & 0 deletions maitake-sync/src/mutex/tests.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use mutex_traits::ScopedRawMutex;

use crate::loom::{self, future};
use crate::Mutex;

Expand Down Expand Up @@ -54,3 +56,50 @@ fn basic_multi_threaded() {
})
});
}

struct NopRawMutex;

unsafe impl ScopedRawMutex for NopRawMutex {
fn try_with_lock<R>(&self, _: impl FnOnce() -> R) -> Option<R> {
None
}

fn with_lock<R>(&self, _: impl FnOnce() -> R) -> R {
unimplemented!("this doesn't actually do anything")
}

fn is_locked(&self) -> bool {
true
}
}

fn assert_future<F: core::future::Future>(_: F) {}

#[test]
fn lock_future_impls_future() {
loom::model(|| {
// Mutex with `DefaultMutex` as the `ScopedRawMutex` implementation
let mutex = Mutex::new(());
assert_future(mutex.lock());

// Mutex with a custom `ScopedRawMutex` implementation
let mutex = Mutex::new_with_raw_mutex((), NopRawMutex);
assert_future(mutex.lock());
})
}

#[test]
#[cfg(feature = "alloc")]
fn lock_owned_future_impls_future() {
loom::model(|| {
use alloc::sync::Arc;

// Mutex with `DefaultMutex` as the `ScopedRawMutex` implementation
let mutex = Arc::new(Mutex::new(()));
assert_future(mutex.lock_owned());

// Mutex with a custom `ScopedRawMutex` implementation
let mutex = Arc::new(Mutex::new_with_raw_mutex((), NopRawMutex));
assert_future(mutex.lock_owned());
})
}

0 comments on commit 12c5b21

Please sign in to comment.