surelock 0.1.0

Deadlock-free locks for Rust with compile time guarantees, incremental locks, and atomic lock sets.
Documentation
#![allow(unsafe_code)]
//! Blanket [`RawMutex`] impl for `lock_api::RawMutex`.
//!
//! This module is available behind the `lock-api` feature and bridges
//! any `lock_api::RawMutex` implementation (`parking_lot`, `spin`, etc.)
//! to surelock's trait. No newtype wrappers needed -- use the backend
//! type directly as the `R` parameter on `Mutex<T, R>`.

use super::RawMutex;

/// RAII guard that unlocks a [`lock_api::RawMutex`] on drop.
///
/// This is a thin wrapper: `lock()` acquires the lock, and `Drop`
/// calls `unlock()`.
pub struct LockApiGuard<'a, R: lock_api::RawMutex>(&'a R);

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

impl<R: lock_api::RawMutex> Drop for LockApiGuard<'_, R> {
    fn drop(&mut self) {
        // SAFETY: the guard only exists while the lock is held.
        unsafe {
            self.0.unlock();
        }
    }
}

unsafe impl<R: lock_api::RawMutex> RawMutex for R {
    type Guard<'a>
        = LockApiGuard<'a, R>
    where
        R: 'a;

    fn new() -> Self {
        R::INIT
    }

    fn lock(&self) -> Self::Guard<'_> {
        lock_api::RawMutex::lock(self);
        LockApiGuard(self)
    }

    fn try_lock(&self) -> Option<Self::Guard<'_>> {
        if lock_api::RawMutex::try_lock(self) {
            Some(LockApiGuard(self))
        } else {
            None
        }
    }
}