Crate mutcy

Source
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.

  1. Borrowing is zero-cost.
  2. Borrowing will never fail or panic.
  3. 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.
KeyCellMut
Wraps a mutably borrowed reference to a value in a KeyCell.
KeyCellRef
Wraps an immutably borrowed reference to a value in a KeyCell.

Traits§

Meta
Defines constant metadata to be stored alongside the primary item in a KeyCell.

Type Aliases§

KeyMut
Mutable reference to KeyCellMut.
KeyRef
Reference to KeyCellRef.