guarded.rs
Overview
This file provides a set of traits and implementations to facilitate safe, synchronized access to inner data protected by a mutex wrapper. It defines abstractions for guarded (immutable) and guarded mutable access patterns, especially in multi-threaded contexts where data must be locked and unlocked properly. The main focus is on using Arc<Mutex<T>> to allow shared ownership and mutually exclusive access to the inner data.
The traits allow executing closures on the locked inner data, abstracting away manual locking and unlocking. Additionally, support for "try" locking (non-blocking lock attempts) is provided. The design also includes a customizable mechanism (AllowGuardedMut) to allow inner types to control how mutable access is provided.
Traits and Their Purpose
AllowGuardedMut
pub trait AllowGuardedMut {
fn inner_guarded_mut<F, T>(&mut self, action: F) -> T
where
F: FnOnce(&mut Self) -> T,
{
action(self)
}
}
Purpose: This trait allows customizing how mutable access is performed on the inner object. By default, it simply calls the provided closure on
self.Parameters:
action: A closure that takes a mutable reference toSelfand returns some value.
Return value: The result of the closure execution.
Usage: Inner types can implement this trait to override or wrap the mutable access logic.
Guarded<Inner>
pub trait Guarded<Inner> {
fn guarded<F, T>(&self, action: F) -> T
where
F: FnOnce(&Inner) -> T;
}
Purpose: Defines a method for safely accessing an immutable reference to an inner type within a guarded context.
Parameters:
action: A closure taking an immutable reference toInnerand returning a value.
Return value: The result of the closure.
Usage: Typically used for read-only operations on the guarded data.
GuardedMut<Inner>
pub trait GuardedMut<Inner> {
fn guarded_mut<F, T>(&self, action: F) -> T
where
F: FnOnce(&mut Inner) -> T;
}
Purpose: Defines a method for safely accessing a mutable reference to the inner data.
Parameters:
action: A closure taking a mutable reference toInnerand returning a value.
Return value: The result of the closure.
Usage: For performing mutations on the inner data within a locking context.
TryGuardedMut<Inner>
pub trait TryGuardedMut<Inner> {
fn try_guarded_mut<F, T>(&self, action: F) -> Option<T>
where
F: FnOnce(&mut Inner) -> T;
}
Purpose: Provides a non-blocking attempt to access mutable inner data, returning
Noneif the lock cannot be acquired.Parameters:
action: A closure taking a mutable reference and returning a value.
Return value:
Some(result)if the lock was successfully acquired and the closure executed;Noneotherwise.
Implementations
All implemented for Arc<Mutex<Inner>> type, leveraging the parking_lot::Mutex for efficient locking.
Guarded<Inner> for Arc<Mutex<Inner>>
Locks the mutex immutably, executes the closure with the locked reference, then unlocks.
Ensures safe immutable access to inner data.
Implementation detail: Drops the lock guard explicitly after closure execution to release the lock immediately.
GuardedMut<Inner> for Arc<Mutex<Inner>> where Inner: AllowGuardedMut
Locks the mutex mutably, then delegates mutable access to the inner
Innertype via theAllowGuardedMuttrait.Allows inner type to customize how mutable access is handled.
Drops the lock guard after closure execution.
TryGuardedMut<Inner> for Arc<Mutex<Inner>> where Inner: AllowGuardedMut
Attempts a non-blocking lock with
try_lock().If lock acquired, delegates mutable access to inner type via
AllowGuardedMut.Returns
Noneif lock acquisition fails.
Important Implementation Details
Uses
parking_lot::Mutexinstead of the standard library mutex for improved performance and ergonomics.The explicit dropping of the lock guard (
drop(guard)) immediately after closure execution releases the lock early, which can help reduce contention in concurrent scenarios.The
AllowGuardedMuttrait is introduced as a customization point for mutable access, potentially enabling inner types to embed additional logic during mutable access (e.g., conditional locking, additional validation).The
TryGuardedMuttrait supports non-blocking lock attempts, useful in scenarios where waiting on a lock is undesirable.
Interaction with Other Parts of the System
This file acts as a utility layer for safely accessing shared mutable state wrapped in
Arc<Mutex<T>>.Other components that require thread-safe mutable or immutable access to shared data can use these traits to abstract away direct locking.
The design encourages encapsulation of locking logic, reducing boilerplate and potential locking errors elsewhere in the codebase.
The use of
Arcenables reference-counted shared ownership, making this suitable for scenarios requiring concurrent read/write access across threads.The traits and implementations here are foundational for concurrency management and synchronization patterns.
Usage Examples
Immutable access example
use std::sync::Arc;
use parking_lot::Mutex;
let data = Arc::new(Mutex::new(42));
let result = data.guarded(|val| *val + 1);
assert_eq!(result, 43);
Mutable access example with AllowGuardedMut default
use std::sync::Arc;
use parking_lot::Mutex;
let data = Arc::new(Mutex::new(5));
data.guarded_mut(|val| *val += 10);
assert_eq!(data.guarded(|val| *val), 15);
Try mutable access example
use std::sync::Arc;
use parking_lot::Mutex;
let data = Arc::new(Mutex::new(100));
if let Some(new_val) = data.try_guarded_mut(|val| {
*val += 1;
*val
}) {
println!("New value: {}", new_val);
} else {
println!("Could not acquire lock");
}
Mermaid Class Diagram
classDiagram
class AllowGuardedMut {
+inner_guarded_mut()
}
class Guarded~Inner~ {
+guarded()
}
class GuardedMut~Inner~ {
+guarded_mut()
}
class TryGuardedMut~Inner~ {
+try_guarded_mut()
}
class ArcMutex~Inner~ {
<<implements>> Guarded~Inner~
<<implements>> GuardedMut~Inner~
<<implements>> TryGuardedMut~Inner~
}
AllowGuardedMut <|.. ArcMutex~Inner~
Guarded~Inner~ <|.. ArcMutex~Inner~
GuardedMut~Inner~ <|.. ArcMutex~Inner~
TryGuardedMut~Inner~ <|.. ArcMutex~Inner~
This diagram shows the key traits defined in the file and their implementation by Arc<Mutex<Inner>>, illustrating the trait-based abstraction of guarded access mechanisms.