Skip to main content

KeyHandle

Struct KeyHandle 

Source
pub struct KeyHandle { /* private fields */ }
Expand description

Per-thread capability to create lock scopes.

The root of authority for lock acquisition on its thread. Claimed once per thread via try_claim or claim, and provides scope for creating MutexKeys inside a branded-lifetime closure.

scope(&mut self) takes a mutable borrow, so the borrow checker prevents nesting at compile time – no runtime check needed. This is the static alternative to try_lock_scope / lock_scope (which are std-only and use runtime checks).

!Clone, !Copy, !Send, !Sync.

§Per-Thread, Not Global

Each thread claims its own handle. Cross-thread deadlock prevention comes from LockSet’s sorted acquisition and LockAfter’s level ordering – those are properties of the locks, not the handle.

§Storage Model

On std, each thread has a KeyHandle pre-allocated in thread_local! storage. try_claim takes it out (.take()), and Drop puts it back. This ensures at most one active handle per thread by construction.

On no_std, try_claim always succeeds (no thread_local!). This is dangerous – multiple handles can coexist, creating independent keys that defeat the ordering guarantee. On no_std, use Locksmith to distribute handles explicitly, originating from a single root of authority. The &mut self on scope prevents nesting within a single handle but not across multiple handles.

§Examples

use surelock::{key_handle::KeyHandle, mutex::Mutex};

let mut handle = KeyHandle::claim();

handle.scope(|key| {
    let m: Mutex<u32> = Mutex::new(42);
    let (guard, _key) = key.lock(&m);
    assert_eq!(*guard, 42);
});

// Sequential scopes are fine
handle.scope(|key| {
    // fresh scope, new key at Bottom
});

// Nesting is a compile error:
// handle.scope(|key1| {
//     handle.scope(|key2| { ... });
//     ^^^^ error: already mutably borrowed
// });

Implementations§

Source§

impl KeyHandle

Source

pub fn try_claim() -> Option<Self>

Try to claim the KeyHandle for the current thread.

On std: takes the handle from thread_local! storage. Returns None if already claimed (by a previous try_claim or an active try_lock_scope / lock_scope).

On no_std: always returns Some (no thread_local! available for uniqueness checking). This is dangerous – multiple handles on the same execution context can create independent keys that defeat the ordering guarantee. On no_std, prefer using Locksmith to distribute KeyHandles explicitly, and thread the handle via &mut references. The &mut self on scope prevents nesting within a single handle, but cannot prevent multiple handles from coexisting.

Source

pub fn claim() -> Self

Claim the KeyHandle for the current thread, panicking if already claimed.

§Panics

Panics if a KeyHandle or active lock scope already exists on this thread.

Source

pub fn scope<F, Ret>(&mut self, f: F) -> Ret
where F: for<'scope> FnOnce(MutexKey<'scope, Bottom>) -> Ret,

Provide a MutexKey to the closure for ordered lock acquisition.

Takes &mut self – the borrow checker prevents calling scope while already inside a scope (compile error, not runtime check). This is the static nesting prevention mechanism.

The key starts at Bottom and advances through levels as locks are acquired.

Trait Implementations§

Source§

impl Debug for KeyHandle

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Drop for KeyHandle

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.