surelock 0.1.0

Deadlock-free locks for Rust with compile time guarantees, incremental locks, and atomic lock sets.
Documentation
#![allow(unsafe_code)]
//! RAII guard for [`super::Mutex`].
//!
//! A [`MutexGuard`] provides exclusive access to the data protected
//! by a mutex. Dropping the guard releases the lock (by dropping the
//! inner [`RawMutex::Guard`]).

use core::{
    cell::UnsafeCell,
    ops::{Deref, DerefMut},
};

use crate::raw_mutex::RawMutex;

/// RAII guard for a [`super::Mutex`].
///
/// Provides `Deref` and `DerefMut` access to the protected data.
/// The lock is released when the guard is dropped.
///
/// Guards are not constructible by users -- they are returned by
/// [`MutexKey::lock`](crate::key::MutexKey::lock),
/// [`MutexKey::lock_with`](crate::key::MutexKey::lock_with), or
/// `Mutex::unchecked_lock`
/// (if the `escape-hatch` feature is enabled).
#[must_use = "if unused, the Mutex will immediately unlock"]
pub struct MutexGuard<'a, R: RawMutex + 'a, T: ?Sized> {
    // Field order matters: Rust drops fields in declaration order.
    // `data` is declared first so its borrow is released before
    // `_raw_guard` drops and releases the lock.
    pub(crate) data: &'a UnsafeCell<T>,
    pub(crate) _raw_guard: R::Guard<'a>,
}

impl<R: RawMutex, T: ?Sized> Deref for MutexGuard<'_, R, T> {
    type Target = T;

    fn deref(&self) -> &T {
        // SAFETY: the raw guard guarantees exclusive access.
        unsafe { &*self.data.get() }
    }
}

impl<R: RawMutex, T: ?Sized> DerefMut for MutexGuard<'_, R, T> {
    fn deref_mut(&mut self) -> &mut T {
        // SAFETY: the raw guard guarantees exclusive access.
        unsafe { &mut *self.data.get() }
    }
}

// No Drop impl needed -- dropping _raw_guard releases the lock.

impl<R: RawMutex, T: ?Sized + core::fmt::Debug> core::fmt::Debug for MutexGuard<'_, R, T> {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        core::fmt::Debug::fmt(&**self, f)
    }
}

// SAFETY: MutexGuard is Send if the raw guard is Send and T is Send.
unsafe impl<'a, R: RawMutex + 'a, T: ?Sized + Send> Send for MutexGuard<'a, R, T> where
    R::Guard<'a>: Send
{
}

// SAFETY: MutexGuard is Sync if T is Sync (shared ref to guard = shared ref to data).
unsafe impl<'a, R: RawMutex + 'a, T: ?Sized + Sync> Sync for MutexGuard<'a, R, T> where
    R::Guard<'a>: Sync
{
}