pub struct JailCell<T> { /* private fields */ }Expand description
Represents a single standalone value that allows interior mutability while upholding memory safety with a reference counting usize
This is a very simple implementation of the principles found in Prison
It has a single UnsafeCell to allow interior mutability. The UnsafeCell holds
one single usize to track mutable and immutable references, and the value itself
of type T
It has visit_ref(), visit_mut(), guard_ref(), and guard_mut() methods, just like Prison,
but with drastically simpler requirements for safety checking.
§Example
let string_jail: JailCell<String> = JailCell::new(String::from("'Bad-Guy' Bert"));
string_jail.visit_mut(|criminal| {
let bigger_bad = String::from("Dr. Lego-Step");
println!("Breaking News: {} to be set free to make room for {}", *criminal, bigger_bad);
*criminal = bigger_bad;
Ok(())
})?;
let guarded_criminal = string_jail.guard_ref()?;
println!("{} will now be paraded around town for public shaming", *guarded_criminal);
assert_eq!(*guarded_criminal, String::from("Dr. Lego-Step"));
JailValueRef::unguard(guarded_criminal);Implementations§
Source§impl<T> JailCell<T>
impl<T> JailCell<T>
Sourcepub fn new(value: T) -> JailCell<T>
pub fn new(value: T) -> JailCell<T>
Creates a new JailCell with the supplied value of type T
After creation, mutable or immutable references to it’s value can only be obtained
through its visit_*() or guard_*() methods
Sourcepub fn visit_mut<F>(&self, operation: F) -> Result<(), AccessError>
pub fn visit_mut<F>(&self, operation: F) -> Result<(), AccessError>
Obtain a mutable reference to the JailCell’s internal value that gets passed to a closure you provide.
§Example
let string_jail: JailCell<String> = JailCell::new(String::from("'Bad-Guy' Bert"));
string_jail.visit_mut(|criminal| {
let bigger_bad = String::from("Dr. Lego-Step");
println!("Breaking News: {} to be set free to make room for {}", *criminal, bigger_bad);
*criminal = bigger_bad;
Ok(())
})?;§Errors
- [AccessError::ValueAlreadyMutablyReferenced(0)] if value is already mutably referenced
- [AccessError::ValueStillImmutablyReferenced(0)] if value has any number of immutable references
§Example
let jail: JailCell<u32> = JailCell::new(42);
jail.visit_mut(|val| {
assert!(jail.visit_mut(|val| Ok(())).is_err());
Ok(())
})?;
jail.visit_ref(|val| {
assert!(jail.visit_mut(|val| Ok(())).is_err());
Ok(())
})?;Sourcepub fn visit_ref<F>(&self, operation: F) -> Result<(), AccessError>
pub fn visit_ref<F>(&self, operation: F) -> Result<(), AccessError>
Obtain an immutable reference to the JailCell’s internal value that gets passed to a closure you provide.
§Example
let string_jail: JailCell<String> = JailCell::new(String::from("'Bad-Guy' Bert"));
string_jail.visit_ref(|criminal| {
println!("Breaking News: {} was just captured!", *criminal);
Ok(())
})?;§Errors
- [AccessError::ValueAlreadyMutablyReferenced(0)] if value is already mutably referenced
- [AccessError::MaximumImmutableReferencesReached(0)] if value has usize::MAX - 2 immutable references already
§Example
let jail: JailCell<u32> = JailCell::new(42);
jail.visit_mut(|val| {
assert!(jail.visit_ref(|val| Ok(())).is_err());
Ok(())
})?;Sourcepub fn guard_mut<'a>(&'a self) -> Result<JailValueMut<'a, T>, AccessError>
pub fn guard_mut<'a>(&'a self) -> Result<JailValueMut<'a, T>, AccessError>
Obtain an JailValueMut that marks the JailCell mutably referenced as long as it remains in scope and automatically unlocks it when it falls out of scope
JailValueMut
You may manually drop the JailValueMut out of scope by passing it to the function [JailValueMut::unguard(_jail_val_mut)]
§Example
let string_jail: JailCell<String> = JailCell::new(String::from("'Bad-Guy' Bert"));
let mut grd_criminal = string_jail.guard_mut()?;
let bigger_bad = String::from("Dr. Lego-Step");
println!("Breaking News: {} to be set free to make room for {}", *grd_criminal, bigger_bad);
*grd_criminal = bigger_bad;
JailValueMut::unguard(grd_criminal);§Errors
- [AccessError::ValueAlreadyMutablyReferenced(0)] if value is already mutably referenced
- [AccessError::ValueStillImmutablyReferenced(0)] if value has any number of immutable references
§Example
let jail: JailCell<u32> = JailCell::new(42);
let guard_ref = jail.guard_ref()?;
assert!(jail.guard_mut().is_err());
JailValueRef::unguard(guard_ref);
let guard_mut = jail.guard_mut()?;
assert!(jail.guard_mut().is_err());
JailValueMut::unguard(guard_mut);Sourcepub fn guard_ref<'a>(&'a self) -> Result<JailValueRef<'a, T>, AccessError>
pub fn guard_ref<'a>(&'a self) -> Result<JailValueRef<'a, T>, AccessError>
Obtain an JailValueRef that marks the JailCell mutably referenced as long as it remains in scope and automatically unlocks it when it falls out of scope
JailValueRef
You may manually drop the JailValueRef out of scope by passing it to the function [JailValueRef::unguard(_jail_val_ref)]
§Example
let string_jail: JailCell<String> = JailCell::new(String::from("'Bad-Guy' Bert"));
let grd_criminal = string_jail.guard_ref()?;
println!("Breaking News: {} has been captured!", *grd_criminal);
JailValueRef::unguard(grd_criminal);§Errors
- [AccessError::ValueAlreadyMutablyReferenced(0)] if value is already mutably referenced
- [AccessError::MaximumImmutableReferencesReached(0)] if value has usize::MAX - 2 immutable references already
§Example
let jail: JailCell<u32> = JailCell::new(42);
let guard_mut = jail.guard_mut()?;
assert!(jail.guard_ref().is_err());
JailValueMut::unguard(guard_mut);Sourcepub fn clone_val(&self) -> Twhere
T: Clone,
pub fn clone_val(&self) -> Twhere
T: Clone,
Clones the requested value out of the JailCell into a new variable
Only available when type T implements Clone (it is assumed that the implementation of T::clone() is memory safe).
Because cloning does not alter the original, and because the new variable to hold the clone does not have any presumtions about the value, it is safe (in a single-threaded context) to clone out the value even if it is being visited or guarded.
§Example
let jail: JailCell<String> = JailCell::new(String::from("Dolly"));
let guard_mut = jail.guard_mut()?;
let dolly_2 = jail.clone_val();
JailValueMut::unguard(guard_mut);
assert_eq!(dolly_2, String::from("Dolly"));Sourcepub unsafe fn peek_ref<'a>(&'a self) -> &'a T
pub unsafe fn peek_ref<'a>(&'a self) -> &'a T
Get a reference to the value while ignoring reference counting and most other safety measures
This method is provided as a way for libraries depending on this code to perform niche
optimized reads of contained values without the overhead of the normal safety checks,
or when a mutable reference is active but you can statically confirm that the value will
not be mutated from the begining of the returned &T’s lifetime to the end of it’s lifetime.
The returned reference is intended to be short-lived and safely contained in a scope where no mutation of the value takes place
§Safety
When you call this method and as long as the &T it returns remains in-scope/alive,
you MUST ensure the following:
- The value MUST NOT be mutated by ANY source, including active safe reference-counted mutable references
- NO operation can be performed that could potentially cause the underlying memory address of the JailCell’s data to relocate