surelock 0.1.0

Deadlock-free locks for Rust with compile time guarantees, incremental locks, and atomic lock sets.
Documentation
#![allow(unsafe_code)]
//! [`RawMutex`] backend using `std::sync::Mutex`.
//!
//! [`StdMutex`] wraps `std::sync::Mutex<()>` and implements surelock's
//! [`RawMutex`] trait. Poisoned mutexes panic on
//! acquisition -- consistent with the near-universal `.lock().unwrap()`
//! pattern and with surelock's position that poisoning is orthogonal
//! to deadlock prevention (see ADR-7).
//!
//! This is the default backend when the `std` feature is enabled.

extern crate std;

use std::sync;

use super::RawMutex;

/// A raw mutex backed by [`std::sync::Mutex`].
///
/// Panics if the underlying `std::sync::Mutex` is poisoned (a panic
/// previously unwound through a critical section). This matches the
/// `.lock().unwrap()` convention used by the vast majority of
/// `std::sync::Mutex` users.
pub struct StdMutex {
    inner: sync::Mutex<()>,
}

impl StdMutex {
    /// Create a new unlocked `StdMutex`.
    #[must_use]
    pub const fn const_new() -> Self {
        Self {
            inner: sync::Mutex::new(()),
        }
    }
}

impl Default for StdMutex {
    fn default() -> Self {
        Self::const_new()
    }
}

impl core::fmt::Debug for StdMutex {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        f.debug_struct("StdMutex").finish_non_exhaustive()
    }
}

unsafe impl RawMutex for StdMutex {
    type Guard<'a> = sync::MutexGuard<'a, ()>;

    fn new() -> Self {
        Self::const_new()
    }

    #[allow(clippy::expect_used)] // Intentional -- poisoned mutex should panic loudly
    fn lock(&self) -> Self::Guard<'_> {
        self.inner
            .lock()
            .expect("surelock: mutex poisoned (a panic occurred in a critical section)")
    }

    #[allow(clippy::panic)] // Intentional -- poisoned mutex should panic loudly
    fn try_lock(&self) -> Option<Self::Guard<'_>> {
        match self.inner.try_lock() {
            Ok(guard) => Some(guard),
            Err(sync::TryLockError::WouldBlock) => None,
            Err(sync::TryLockError::Poisoned(_)) => {
                panic!("surelock: mutex poisoned (a panic occurred in a critical section)");
            }
        }
    }
}

// SAFETY: std::sync::Mutex<()> is Send + Sync.
unsafe impl Send for StdMutex {}
unsafe impl Sync for StdMutex {}