Skip to content

Commit

Permalink
sketch out DefaultMutex
Browse files Browse the repository at this point in the history
  • Loading branch information
hawkw committed Jul 28, 2024
1 parent ea65e8e commit 1ad4f2e
Show file tree
Hide file tree
Showing 5 changed files with 166 additions and 1 deletion.
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions maitake-sync/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,15 @@ rust-version = "1.61.0"
[features]
default = ["alloc"]
alloc = ["cordyceps/alloc"]
std = ["alloc"]
no-cache-pad = ["cordyceps/no-cache-pad"]
core-error = []

[dependencies]
mycelium-bitfield = { version = "0.1.3", path = "../bitfield" }
mutex-traits = "0.999.0"
cordyceps = { version = "0.3.0", path = "../cordyceps" }
critical-section = { version = "1.1", optional = true }
pin-project = "1"
portable-atomic = "1.2"
tracing = { version = "0.1", default_features = false, optional = true }
Expand Down
2 changes: 2 additions & 0 deletions maitake-sync/src/blocking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,10 @@
//! [`lock_api`]: https://crates.io/crates/lock_api
//! [`critical-section`]: https://crates.io/crates/critical-section
//! [`std::sync::Mutex`]: https://doc.rust-lang.org/stable/std/sync/struct.Mutex.html
mod default_mutex;
pub(crate) mod mutex;
pub(crate) mod rwlock;

pub use self::{mutex::*, rwlock::*};
pub use default_mutex::DefaultMutex;
pub use mutex_traits::ConstInit;
154 changes: 154 additions & 0 deletions maitake-sync/src/blocking/default_mutex.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
#[cfg(loom)]
pub use loom_impl::DefaultMutex;

#[cfg(all(not(loom), feature = "std"))]
pub use std_impl::DefaultMutex;

#[cfg(all(not(loom), not(feature = "std"), feature = "critical-section"))]
pub use cs_impl::DefaultMutex;

#[cfg(all(not(loom), not(feature = "std"), not(feature = "critical-section")))]
pub use spin_impl::DefaultMutex;

#[cfg(loom)]
mod loom_impl {
#[cfg(feature = "tracing")]
use core::panic::Location;
use mutex_traits::ScopedRawMutex;

pub struct DefaultMutex(loom::sync::Mutex<()>);

unsafe impl ScopedRawMutex for DefaultMutex {
#[track_caller]
fn with_lock<R>(&self, f: impl FnOnce() -> R) -> R {
#[cfg(feature = "tracing")]
let location = Location::caller();
#[cfg(feature = "tracing")]
tracing::debug!(%location, "DefaultMutex::with_lock()");

let guard = self.0.lock();
tracing::debug!(%location, "DefaultMutex::with_lock() -> locked");

let result = f();
drop(guard);

#[cfg(feature = "tracing")]
tracing::debug!(%location, "DefaultMutex::with_lock() -> unlocked");

result
}

#[track_caller]
fn try_with_lock<R>(&self, f: impl FnOnce() -> R) -> Option<R> {
#[cfg(feature = "tracing")]
let location = Location::caller();
#[cfg(feature = "tracing")]
tracing::debug!(%location, "DefaultMutex::try_with_lock()");

match self.0.try_lock() {
Ok(guard) => {
#[cfg(feature = "tracing")]
tracing::debug!(%location, "DefaultMutex::try_with_lock() -> locked");

let result = f();
drop(guard);

#[cfg(feature = "tracing")]
tracing::debug!(%location, "DefaultMutex::try_with_lock() -> unlocked");

Some(result)
}
None => {
#[cfg(feature = "tracing")]
tracing::debug!(%location, "DefaultMutex::try_with_lock() -> already locked");

None
}
}
}

fn is_locked(&self) -> bool {
self.0.try_lock().is_none()
}
}
}

#[cfg(all(not(loom), feature = "std"))]
mod std_impl {
use mutex_traits::ScopedRawMutex;

pub struct DefaultMutex(std::sync::Mutex<()>);

unsafe impl ScopedRawMutex for DefaultMutex {
#[track_caller]
#[inline]
fn with_lock<R>(&self, f: impl FnOnce() -> R) -> R {
let _guard = self.0.lock().unwrap();
f()
}

#[track_caller]
fn try_with_lock<R>(&self, f: impl FnOnce() -> R) -> Option<R> {
let _guard = self.0.try_lock().ok()?;
Some(f())
}

fn is_locked(&self) -> bool {
self.0.try_lock().is_none()

Check failure on line 97 in maitake-sync/src/blocking/default_mutex.rs

View workflow job for this annotation

GitHub Actions / cargo check (host)

error[E0599]: no method named `is_none` found for enum `std::result::Result` in the current scope --> maitake-sync/src/blocking/default_mutex.rs:97:31 | 97 | self.0.try_lock().is_none() | ^^^^^^^ help: there is a method with a similar name: `is_ok`

Check failure on line 97 in maitake-sync/src/blocking/default_mutex.rs

View workflow job for this annotation

GitHub Actions / docs

error[E0599]: no method named `is_none` found for enum `std::result::Result` in the current scope --> maitake-sync/src/blocking/default_mutex.rs:97:31 | 97 | self.0.try_lock().is_none() | ^^^^^^^ help: there is a method with a similar name: `is_ok`
}
}
}

#[cfg(all(not(loom), not(feature = "std"), feature = "critical-section"))]
mod cs_impl {
use crate::spin::Spinlock;
use mutex_traits::ScopedRawMutex;

pub struct DefaultMutex(Spinlock);

unsafe impl ScopedRawMutex for DefaultMutex {
#[track_caller]
#[inline]
fn with_lock<R>(&self, f: impl FnOnce() -> R) -> R {
self.0.with_lock(|| critical_section::with(|| f()))
}

#[track_caller]
#[inline]
fn try_with_lock<R>(&self, f: impl FnOnce() -> R) -> Option<R> {
self.0.try_with_lock(|| critical_section::with(|| f()))
}

#[inline]
fn is_locked(&self) -> bool {
self.0.is_locked()
}
}
}

#[cfg(all(not(loom), not(feature = "std"), not(feature = "critical-section")))]
mod spin_impl {
use crate::spin::Spinlock;
use mutex_traits::ScopedRawMutex;

pub struct DefaultMutex(Spinlock);

unsafe impl ScopedRawMutex for DefaultMutex {
#[track_caller]
#[inline]
fn with_lock<R>(&self, f: impl FnOnce() -> R) -> R {
self.0.with_lock(|| critical_section::with(|| f()))

Check failure on line 140 in maitake-sync/src/blocking/default_mutex.rs

View workflow job for this annotation

GitHub Actions / clippy

error[E0433]: failed to resolve: use of undeclared crate or module `critical_section` --> maitake-sync/src/blocking/default_mutex.rs:140:33 | 140 | self.0.with_lock(|| critical_section::with(|| f())) | ^^^^^^^^^^^^^^^^ use of undeclared crate or module `critical_section`
}

#[track_caller]
#[inline]
fn try_with_lock<R>(&self, f: impl FnOnce() -> R) -> Option<R> {
self.0.try_with_lock(|| critical_section::with(|| f()))

Check failure on line 146 in maitake-sync/src/blocking/default_mutex.rs

View workflow job for this annotation

GitHub Actions / clippy

error[E0433]: failed to resolve: use of undeclared crate or module `critical_section` --> maitake-sync/src/blocking/default_mutex.rs:146:37 | 146 | self.0.try_with_lock(|| critical_section::with(|| f())) | ^^^^^^^^^^^^^^^^ use of undeclared crate or module `critical_section`
}

#[inline]
fn is_locked(&self) -> bool {
self.0.is_locked()
}
}
}
2 changes: 1 addition & 1 deletion maitake-sync/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#![doc = include_str!("../README.md")]
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg, doc_cfg_hide))]
#![cfg_attr(docsrs, doc(cfg_hide(docsrs, loom)))]
#![cfg_attr(not(test), no_std)]
#![cfg_attr(not(any(test, feature = "std")), no_std)]
#![cfg_attr(feature = "core-error", feature(error_in_core))]
#![warn(missing_docs, missing_debug_implementations)]

Expand Down

0 comments on commit 1ad4f2e

Please sign in to comment.