surelock 0.1.0

Deadlock-free locks for Rust with compile time guarantees, incremental locks, and atomic lock sets.
Documentation
//! Lock levels and ordering traits.
//!
//! [`Level<N>`] is the const-generic level type. [`LockAfter`] declares
//! that locks at one level may be acquired after locks at another.
//!
//! Users create semantic aliases for numbered levels:
//!
//! ```rust
//! use surelock::level::Level;
//!
//! type Config = Level<0>;
//! type Account = Level<1>;
//! type Transaction = Level<2>;
//! ```
//!
//! For per-instance ordering chains, use
//! [`Mutex::new_higher`](crate::mutex::Mutex::new_higher).

/// Marker trait for lock level types.
///
/// Implemented by [`Bottom`], all [`Level<N>`] types (including
/// [`Base`] = `Level<0>`), and any user-declared level types.
#[diagnostic::on_unimplemented(
    message = "`{Self}` is not a valid lock level",
    note = "lock levels must implement the `IsLevel` trait; use `Level<N>`, `Base`, or manually implement `IsLevel`"
)]
pub trait IsLevel {}

/// Marker trait: locks at level `Self` may be acquired after locks
/// at level `Before` are already held.
///
/// This is a _safe_ trait. A cyclic implementation defeats deadlock
/// prevention but cannot cause undefined behavior -- cycles cause a
/// liveness failure (potential deadlock), not a safety failure.
#[diagnostic::on_unimplemented(
    message = "`{Self}` cannot be acquired after `{Before}`",
    note = "locks must be acquired in ascending level order; once a higher-levelled lock is held, lower-levelled locks cannot be acquired for this key"
)]
pub trait LockAfter<Before: IsLevel>: IsLevel {}

/// Maps a level to its successor.
///
/// Used by [`Mutex::new_higher`](crate::mutex::Mutex::new_higher) to
/// auto-increment levels when chaining mutex creation.
///
/// Implemented for `Level<0>` through `Level<14>` (default, 16 levels).
/// Enable the `levels-32` or `levels-64` feature for more depth.
#[diagnostic::on_unimplemented(
    message = "`{Self}` has no next level (maximum depth reached)",
    note = "the default maximum lock depth is 16 levels; enable the `levels-32` or `levels-64` feature for more, or flatten your hierarchy using `LockSet` for same-depth siblings"
)]
pub trait NextLevel: IsLevel {
    /// The next level after `Self`.
    type Next: IsLevel;
}

/// Computes the minimum of two levels.
///
/// Used by multi-level [`LockSet`](crate::set::LockSet) to determine
/// the lowest level in a set.
pub trait MinLevel<Other: IsLevel>: IsLevel {
    /// The lower of `Self` and `Other`.
    type Min: IsLevel;
}

/// Computes the maximum of two levels.
///
/// Used by multi-level [`LockSet`](crate::set::LockSet) to determine
/// the highest level in a set.
pub trait MaxLevel<Other: IsLevel>: IsLevel {
    /// The higher of `Self` and `Other`.
    type Max: IsLevel;
}

/// Extracts the lock level from a mutex reference, regardless of
/// wrapper type (`Arc`, `Rc`, `Box`, or bare reference).
///
/// Used by [`MaxLevelOf`] to support smart-pointer-wrapped mutexes
/// in [`Mutex::new_higher`](crate::mutex::Mutex::new_higher).
pub trait MutexLevel {
    /// The level of the referenced mutex.
    type Lvl: IsLevel;
}

/// Extracts the maximum level from a collection of mutex references.
///
/// Used by [`Mutex::new_higher`](crate::mutex::Mutex::new_higher) to determine
/// the level of a mutex created after multiple parents.
pub trait MaxLevelOf {
    /// The maximum level across all elements.
    type Max: IsLevel;
}

// Single parent: delegate to MutexLevel.
impl<A: MutexLevel> MaxLevelOf for A {
    type Max = A::Lvl;
}

// 2-tuple: max of two MutexLevel types.
impl<A: MutexLevel, B: MutexLevel> MaxLevelOf for (A, B)
where
    A::Lvl: MaxLevel<B::Lvl>,
{
    type Max = <A::Lvl as MaxLevel<B::Lvl>>::Max;
}

/// Create a child mutex ordered after one or more parents.
///
/// The child's level is `max(parent levels) + 1`, and its backend
/// `R` is inherited from the parent(s). Implemented for single
/// mutexes, smart-pointer-wrapped mutexes (`Arc`, `Rc`, `Box`),
/// and 2-tuples of any combination (with the same backend `R`).
///
/// # Examples
///
/// ```rust
/// use surelock::{level::NewHigher, mutex::Mutex};
///
/// let config: Mutex<u32> = Mutex::new(10);
/// let account = config.new_higher(20u32);     // Level<1>
/// let txn = account.new_higher(30u32);        // Level<2>
/// ```
pub trait NewHigher<ChildT, R: crate::raw_mutex::RawMutex> {
    /// The child's level (parent max + 1).
    type NextLvl: IsLevel;

    /// Create a child mutex at the next level.
    fn new_higher(&self, data: ChildT) -> crate::mutex::Mutex<ChildT, Self::NextLvl, R>;
}

/// The bottom of the level ordering.
///
/// Initial state of [`MutexKey`](crate::key::MutexKey) when created
/// by [`KeyHandle::scope`](crate::key_handle::KeyHandle::scope). Not a valid level for
/// mutexes -- only used internally.
#[derive(Debug, Clone, Copy)]
pub struct Bottom;

impl IsLevel for Bottom {}

/// Const-generic lock level.
///
/// `Level<0>` is the default mutex level (aliased as [`Base`]).
/// Higher numbers represent deeper levels in the acquisition
/// ordering.
///
/// Create semantic aliases for your domain:
///
/// ```rust
/// use surelock::level::Level;
///
/// type Database = Level<7>;
/// type Table = Level<8>;
/// type Row = Level<9>;
/// ```
pub struct Level<const N: usize>;

impl<const N: usize> core::fmt::Debug for Level<N> {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        write!(f, "Level<{N}>")
    }
}

#[allow(clippy::expl_impl_clone_on_copy)]
impl<const N: usize> Clone for Level<N> {
    fn clone(&self) -> Self {
        *self
    }
}

impl<const N: usize> Copy for Level<N> {}

/// Default lock level. Alias for `Level<0>`.
pub type Base = Level<0>;

// -- Impl generation macros --

macro_rules! generate_level_impls {
    ($max:expr, [$($n:expr),*]) => {
        // IsLevel + LockAfter<Bottom> for each level
        $(
            impl IsLevel for Level<$n> {}
            impl LockAfter<Bottom> for Level<$n> {}
        )*

        // LockAfter for all pairs where A < B
        generate_lock_after_pairs!([$($n),*]);

        // NextLevel: N -> N+1 (except the last)
        generate_next_level!($max, [$($n),*]);

        // MinLevel and MaxLevel for all pairs
        generate_min_max_pairs!([$($n),*]);
    };
}

macro_rules! generate_lock_after_pairs {
    ([$first:expr $(, $rest:expr)*]) => {
        $(
            impl LockAfter<Level<$first>> for Level<$rest> {}
        )*
        generate_lock_after_pairs!([$($rest),*]);
    };
    ([]) => {};
    ([$single:expr]) => {};
}

macro_rules! generate_next_level {
    ($max:expr, [$first:expr, $second:expr $(, $rest:expr)*]) => {
        impl NextLevel for Level<$first> {
            type Next = Level<$second>;
        }
        generate_next_level!($max, [$second $(, $rest)*]);
    };
    ($max:expr, [$last:expr]) => {};
    ($max:expr, []) => {};
}

macro_rules! generate_min_max_pairs {
    ([$($n:expr),*]) => {
        // Self-pairs
        $(
            impl MinLevel<Level<$n>> for Level<$n> {
                type Min = Level<$n>;
            }
            impl MaxLevel<Level<$n>> for Level<$n> {
                type Max = Level<$n>;
            }
        )*

        // Cross-pairs
        generate_min_max_cross!([$($n),*]);
    };
}

macro_rules! generate_min_max_cross {
    ([$first:expr $(, $rest:expr)*]) => {
        $(
            impl MinLevel<Level<$rest>> for Level<$first> {
                type Min = Level<$first>;
            }
            impl MinLevel<Level<$first>> for Level<$rest> {
                type Min = Level<$first>;
            }
            impl MaxLevel<Level<$rest>> for Level<$first> {
                type Max = Level<$rest>;
            }
            impl MaxLevel<Level<$first>> for Level<$rest> {
                type Max = Level<$rest>;
            }
        )*
        generate_min_max_cross!([$($rest),*]);
    };
    ([]) => {};
    ([$single:expr]) => {};
}

// -- Generate impls --

#[cfg(not(any(feature = "levels-32", feature = "levels-64")))]
generate_level_impls!(16, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);

#[cfg(all(feature = "levels-32", not(feature = "levels-64")))]
generate_level_impls!(
    32,
    [
        0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
        25, 26, 27, 28, 29, 30, 31
    ]
);

#[cfg(feature = "levels-64")]
generate_level_impls!(
    64,
    [
        0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
        25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
        48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63
    ]
);