surelock 0.1.0

Deadlock-free locks for Rust with compile time guarantees, incremental locks, and atomic lock sets.
Documentation
//! # Surelock: Deadlock-Free Locks for Rust
//!
//! Surelock prevents deadlocks by breaking the circular-wait Coffman
//! condition via two complementary mechanisms:
//!
//! 1. [`LockSet`](crate::set::LockSet) -- granular atomic acquisition of multiple locks at the
//!    same level, sorted by a monotonic [`LockId`](crate::id::LockId) assigned at
//!    creation. Safe by construction, infallible.
//! 2. **Levels** -- coarse types declaring a compile-time ordering via
//!    [`LockAfter`](crate::level::LockAfter) trait bounds. A consumed-and-re-emitted
//!    [`MutexKey`](crate::key::MutexKey) tracks the current level as a type parameter.
//!    Wrong-order acquisition is a compile error, not a runtime failure.
//!
//! Every lock call is infallible or doesn't compile. No `Result`,
//! no `Option`, no panic on any lock acquisition path.
//!
//! # Quick Start
//!
//! ```rust
//! use surelock::{key::lock_scope, mutex::Mutex};
//!
//! let counter: Mutex<u32> = Mutex::new(0);
//!
//! lock_scope(|key| {
//!     let (mut guard, _key) = key.lock(&counter);
//!     *guard += 1;
//! });
//! ```
//!
//! # Usage Guide
//!
//! ## Locking a Single Mutex
//!
//! Claim a [`KeyHandle`](crate::key_handle::KeyHandle), then use
//! [`scope`](crate::key_handle::KeyHandle::scope) to enter a scope.
//! Inside the scope, [`lock`](crate::key::MutexKey::lock) acquires
//! the mutex via a closure:
//!
//! ```rust
//! use surelock::{key_handle::KeyHandle, mutex::Mutex};
//!
//! let counter: Mutex<u32> = Mutex::new(0);
//!
//! let mut handle = KeyHandle::claim();
//! handle.scope(|key| {
//!     let (val, _key) = key.lock_with(&counter, |mut guard| {
//!         *guard += 1;
//!         *guard
//!     });
//!     assert_eq!(val, 1);
//! });
//! ```
//!
//! ## Locking Multiple Mutexes Atomically
//!
//! Use a [`LockSet`](crate::set::LockSet) to acquire multiple locks
//! at once, sorted by [`LockId`](crate::id::LockId). This prevents
//! deadlocks by construction -- the order is always consistent:
//!
//! ```rust
//! use surelock::{key_handle::KeyHandle, mutex::Mutex, set::LockSet};
//!
//! let a: Mutex<u32> = Mutex::new(10);
//! let b: Mutex<u32> = Mutex::new(20);
//!
//! let set = LockSet::new((&a, &b));
//!
//! let mut handle = KeyHandle::claim();
//! handle.scope(|key| {
//!     let ((ga, gb), _key) = key.lock(&set);
//!     assert_eq!(*ga + *gb, 30);
//! });
//! ```
//!
//! ## Cross-Level Incremental Acquisition
//!
//! Use [`Mutex::new_higher`](crate::mutex::Mutex::new_higher) to create mutexes at incrementing
//! levels. The [`MutexKey`](crate::key::MutexKey) tracks the current
//! level and the compiler rejects wrong-order acquisition:
//!
//! ```rust
//! use surelock::{key_handle::KeyHandle, level::Level, mutex::Mutex};
//!
//! let config: Mutex<u32> = Mutex::new(42);
//! let account: Mutex<u32, Level<1>> = Mutex::new_higher(100u32, &config);
//!
//! let mut handle = KeyHandle::claim();
//! handle.scope(|key| {
//!     // Read config first (Level<0>)
//!     let (cfg_val, key) = key.lock_with(&config, |g| *g);
//!
//!     // Then lock account (Level<1>)
//!     let ((), _key) = key.lock_with(&account, |mut acct| {
//!         *acct += cfg_val;
//!     });
//! });
//! ```
//!
//! ## Nested Scopes
//!
//! Use [`subscope`](crate::key::MutexKey::subscope) to create a
//! nested locking context within an existing scope. The inner key
//! inherits the outer key's level, and the outer key is consumed
//! for the duration (preventing concurrent use):
//!
//! ```rust
//! use surelock::{key_handle::KeyHandle, mutex::Mutex};
//!
//! let config: Mutex<u32> = Mutex::new(10);
//! let account = Mutex::new_higher(0u32, &config);
//!
//! let mut handle = KeyHandle::claim();
//! handle.scope(|key| {
//!     let (val, key) = key.lock_with(&config, |g| *g);
//!
//!     let (result, _key) = key.subscope(|inner_key| {
//!         let (r, _) = inner_key.lock_with(&account, |mut acct| {
//!             *acct = val;
//!             *acct
//!         });
//!         r
//!     });
//!     assert_eq!(result, 10);
//! });
//! ```
//!
//! # Type Lifecycle
//!
//! ```text
//! ┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┐
//! │ Explicit multi-core
//!//! │      Locksmith
//!         (forge)       │   ┌ ─ ─ ─ ─ ─ ─ ─ ┐
//! │          │              │ std (default)
//!            ▼          │                   │
//! │     KeyVoucher          │   KeyHandle
//!       (deliver)       │        (claim)    │
//! └ ─ ─ ─ ─ ┼ ─ ─ ─ ─ ─ ┘   └ ─ ─ ─ ┼ ─ ─ ─ ┘
//!           │                       │
//!           └────────────┬──────────┘
//!//!//!                     MutexKey
//!                     (scope)
//!//!                        ├───▶ MutexGuard(s)
//!                        │      (access)
//!//!                     MutexKey
//!                    (subscope)
//!//!                        ├───▶ MutexGuard(s)
//!                        │      (access)
//!//!                       ...
//! ```
//!
//! | Type                                            | Role                                       | Created by                                                                                             |
//! |-------------------------------------------------|--------------------------------------------|---------------------------------------------------------------------------------------------------------|
//! | [`Locksmith`](crate::locksmith::Locksmith)      | Factory, issues vouchers (singleton)       | [`Locksmith::new`](crate::locksmith::Locksmith::new)                                                   |
//! | [`KeyVoucher`](crate::key_voucher::KeyVoucher)  | Transferable token (`Send`)                | [`Locksmith::issue`](crate::locksmith::Locksmith::issue)                                               |
//! | [`KeyHandle`](crate::key_handle::KeyHandle)     | Per-thread scope creator (`!Send`)         | [`KeyHandle::claim`](crate::key_handle::KeyHandle::claim) or [`KeyVoucher::redeem`](crate::key_voucher::KeyVoucher::redeem) |
//! | [`MutexKey`](crate::key::MutexKey)              | Per-scope lock token, consumed/re-emitted  | [`handle.scope`](crate::key_handle::KeyHandle::scope)                                                  |
//! | [`MutexGuard`](crate::mutex::guard::MutexGuard) | RAII access to protected data              | [`key.lock`](crate::key::MutexKey::lock) or [`key.lock_with`](crate::key::MutexKey::lock_with)         |
//!
//! ## Key Patterns
//!
//! ```rust,ignore
//! // Enter a scope
//! handle.scope(|key| { ... });
//!
//! // Lock (single mutex or LockSet, guards returned)
//! let (guard, key) = key.lock(&mutex);
//! let ((ga, gb), key) = key.lock(&set);
//!
//! // Lock with closure (one-shot, sorts inline)
//! let (val, key) = key.lock_with(&mutex, |guard| *guard);
//!
//! // Nested sub-scope
//! let (result, key) = key.subscope(|inner_key| { ... });
//! ```
//!
//! ## Construction
//!
//! ```rust,ignore
//! Mutex::new(data)                     // Level<0>, default backend
//! Mutex::new_higher(data, &parent)      // parent.level + 1
//! Mutex::new_higher(data, (&a, &b))     // max(levels) + 1
//!
//! // Method syntax (also works with Arc, Rc, Box)
//! parent.new_higher(data)               // parent.level + 1, inherits backend
//! (&a, &b).new_higher(data)             // max(levels) + 1
//! ```
//!
//! # Levels
//!
//! Locks are ordered by [`Level<N>`](crate::level::Level), a
//! const-generic type. Create semantic aliases for your domain:
//!
//! ```rust
//! use surelock::level::Level;
//!
//! type Database = Level<0>;
//! type Table = Level<1>;
//! type Row = Level<2>;
//! ```
//!
//! Use [`Mutex::new_higher`](crate::mutex::Mutex::new_higher) to chain levels automatically:
//!
//! ```rust
//! use surelock::mutex::Mutex;
//!
//! let db: Mutex<String> = Mutex::new("mydb".into());
//! let table = Mutex::new_higher("users".to_string(), &db);  // Level<1>
//! let row = Mutex::new_higher(42u64, &table);                 // Level<2>
//! ```
//!
//! # Backend Agnostic
//!
//! [`Mutex<T, Lvl, R>`](crate::mutex::Mutex) is generic over any
//! [`RawMutex`](crate::raw_mutex::RawMutex) implementation. `Lvl`
//! defaults to [`Base`](crate::level::Base) (= `Level<0>`) and `R`
//! defaults to [`StdMutex`](crate::raw_mutex::std_mutex::StdMutex)
//! on `std`. Specify just the level to use the default backend:
//! `Mutex<u32, Level<3>>`. For `no_std`, enable the `lock-api`
//! feature and use `spin`, `parking_lot`, or any other
//! `lock_api::RawMutex` backend directly.
//!
//! # Scope Entry
//!
//! There are two ways to enter a lock scope:
//!
//! - **Ambient**: [`lock_scope`](crate::key::lock_scope) / [`try_lock_scope`](crate::key::try_lock_scope) --
//!   convenient, runtime nesting check on `std` (panic / `None`).
//! - **Capability-based**: [`KeyHandle::scope`](crate::key_handle::KeyHandle::scope) --
//!   static nesting prevention via `&mut self` (compile error).
//!   Works on `no_std` without `thread_local!`.
//!
//! On `no_std`, the ambient entry points are not available.
//! [`KeyHandle`](key_handle::KeyHandle) is the only entry mechanism,
//! providing static nesting prevention via `&mut self`. See
//! [`MutexKey::subscope`](crate::key::MutexKey::subscope) for safe nesting within an existing
//! scope on all targets.
//!
//! For a comprehensive guide to `no_std` usage, see
//! [`NO_STD_GUIDE.md`](https://codeberg.org/expede/surelock/src/branch/main/NO_STD_GUIDE.md)
//! in the repository.
//!
//! # Prior Art
//!
//! Surelock builds on ideas from two libraries:
//!
//! - [`happylock`](https://crates.io/crates/happylock) (`botahamec`,
//!   CC0-1.0) -- introduced the `LockCollection` pattern: a
//!   capability token (`ThreadKey`) combined with sorted multi-lock
//!   acquisition. Surelock borrows this pattern, replacing
//!   address-based ordering with a stable monotonic `LockId` counter,
//!   dropping the `std` requirement, and removing `unsafe` from the
//!   public API.
//!
//! - [`lock_tree`](https://crates.io/crates/lock_tree) (Google
//!   Fuchsia, BSD) -- introduced `LockAfter<A>` traits for
//!   compile-time ordering of lock categories, enforced via
//!   witness-token consumption. Surelock extends this with same-level
//!   multi-lock via `LockSet` and makes levels opt-in with a `Base`
//!   default.
//!
//! Neither library alone covers both dynamic multi-lock _and_ static
//! ordering. The combination -- with stable IDs and `no_std`
//! throughout -- is surelock's contribution.
//!
//! Grounded in Coffman, Elphick, and Shoshani's
//! [System Deadlocks](https://uobdv.github.io/Design-Verification/Supplementary/System_Deadlocks-Four_necessary_and_sufficient_conditions_for_deadlock.pdf)
//! (1971).
//!
//! For detailed comparisons, see the
//! [`design/comparison/`](https://codeberg.org/expede/surelock/src/branch/main/design/comparison)
//! directory in the repository.

// Unsafe is forbidden by default. Modules that need it opt in with
// #[allow(unsafe_code)]. See: raw_mutex, mutex, mutex/guard, key_voucher.
#![deny(unsafe_code)]
// Doc links to std-gated items (lock_scope, StdMutex, Mutex::new_higher,
// etc.) resolve correctly on the default std build (docs.rs), but break
// on no_std where those items are cfg'd out.
#![cfg_attr(
    not(feature = "std"),
    allow(rustdoc::broken_intra_doc_links, rustdoc::redundant_explicit_links)
)]
#![no_std]

extern crate alloc;

pub mod acquirable;
mod atomic;
pub mod id;
pub mod key;
pub mod key_handle;
pub mod key_voucher;
pub mod level;
pub mod locksmith;
pub mod mutex;
pub mod raw_mutex;
pub mod set;