Something went wrong. Try again.
🦀🔐 Statically prevent deadlocks crates.io/crates/surelock
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281//! 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 ]);