Expand description
§Zero-Cost Mutable Cyclic Borrows
A RefCell-like dynamic borrowing system that permits recursive borrowing
with zero runtime overhead.
This crate implements KeyCell of which only a single instance can be mutably borrowed at a time using a Key. Simultaneous immutable borrows are permitted.
Key is a ZST, and only a single instance can exist per thread. The only dynamic check this library performs is upon calling Key::acquire to ensure that there exists no other instance.
§Comparison to RefCell
Unlike RefCell, borrows on KeyCells will never fail. They also don’t
need to perform any runtime checks. All borrow checking is performed at
compile time.
- Borrowing is zero-cost.
- Borrowing will never fail or panic.
- Only a single KeyCell can be mutably borrowed per thread.
§Examples
This crate uses borrow and borrow_mut to access data.
use mutcy::{Key, KeyCell, KeyMut};
let mut key = Key::acquire();
let kc1 = KeyCell::new(0i32, ());
let kc2 = KeyCell::new(String::new(), ());
*kc2.borrow_mut(&mut key) += "Hello";
*kc1.borrow_mut(&mut key) += 1;
*kc2.borrow_mut(&mut key) += "World";
let item1 = kc1.borrow(&key);
let item2 = kc1.borrow(&key);
println!("{} - {}", *item1, *item2);With this library it’s possible to define methods that take KeyMut and transfer mutability to other KeyCells when needed. The compile-time borrow checker ensures that no mutable aliasing occurs.
In the following example we show how a struct can accept a self: KeyMut<Self> and relinquish its own borrows to access some other
KeyCell.
#![feature(arbitrary_self_types)]
use mutcy::{Key, KeyCell, KeyMut, Meta};
use std::rc::Rc;
struct MyStruct {
value: i32,
}
impl MyStruct {
fn my_function(self: KeyMut<Self>) {
self.value += 1;
// This relinquishes any borrows to `self`.
let (this, key) = Key::split(self);
// We can now access any other KeyCell using `key`.
let mut string = this.meta().other.borrow_mut(key);
*string += "Hello world";
self.value += 1;
}
}
struct MyStructMeta {
other: Rc<KeyCell<String>>,
}
impl Meta for MyStruct {
type Data = MyStructMeta;
}
let mut key = Key::acquire();
let other = Rc::new(KeyCell::new(String::new(), ()));
let my_struct = KeyCell::new(
MyStruct { value: 0 },
MyStructMeta {
other: other.clone(),
},
);
my_struct.borrow_mut(&mut key).my_function();
println!("{}", *other.borrow(&key));
println!("{}", my_struct.borrow(&key).value);For more information on metadata see Meta.
Structs§
- Key
- A per-thread unique key used to access data inside KeyCells.
- KeyCell
- A
RefCell-like wrapper that can only be accessed via Key. - KeyCell
Mut - Wraps a mutably borrowed reference to a value in a
KeyCell. - KeyCell
Ref - Wraps an immutably borrowed reference to a value in a
KeyCell.
Traits§
Type Aliases§
- KeyMut
- Mutable reference to KeyCellMut.
- KeyRef
- Reference to KeyCellRef.