Crate strong_rc [] [src]

Single-threaded reference-counting pointers.

Unlike std::rc, this is a strong-only Rc meant to be used by caches. The design of this is identical in every respect to std::rc, except for the omission of Weak. Therefore, it can be used as a drop-in replacement.

The type Rc<T> provides shared ownership of a value of type T, allocated in the heap. Invoking clone on Rc produces a new pointer to the same value in the heap. When the last Rc pointer to a given value is destroyed, the pointed-to value is also destroyed.

Shared references in Rust disallow mutation by default, and Rc is no exception. If you need to mutate through an Rc, use Cell or RefCell.

Rc uses non-atomic reference counting. This means that overhead is very low, but an Rc cannot be sent between threads, and consequently Rc does not implement Send. As a result, the Rust compiler will check at compile time that you are not sending Rcs between threads. If you need multi-threaded, atomic reference counting, use sync::Arc.

A cycle between Rc pointers will never be deallocated. If you need cycles, use the Rc from std::rc.

Rc<T> automatically dereferences to T (via the Deref trait), so you can call T's methods on a value of type Rc<T>. To avoid name clashes with T's methods, the methods of Rc<T> itself are associated functions, called using function-like syntax:

use strong_rc::Rc;
let my_rc = Rc::new(());

assert_eq!(Rc::strong_count(&my_rc), 1);

Examples

Consider a scenario where a set of Gadgets are owned by a given Owner. We want to have our Gadgets point to their Owner. We can't do this with unique ownership, because more than one gadget may belong to the same Owner. Rc allows us to share an Owner between multiple Gadgets, and have the Owner remain allocated as long as any Gadget points at it.

use strong_rc::Rc;

struct Owner {
    name: String,
    // ...other fields
}

struct Gadget {
    id: i32,
    owner: Rc<Owner>,
    // ...other fields
}

fn main() {
    // Create a reference-counted `Owner`.
    let gadget_owner: Rc<Owner> = Rc::new(
        Owner {
            name: "Gadget Man".to_string(),
        }
    );

    // Create `Gadget`s belonging to `gadget_owner`. Cloning the `Rc<Owner>`
    // value gives us a new pointer to the same `Owner` value, incrementing
    // the reference count in the process.
    let gadget1 = Gadget {
        id: 1,
        owner: gadget_owner.clone(),
    };
    let gadget2 = Gadget {
        id: 2,
        owner: gadget_owner.clone(),
    };

    // Dispose of our local variable `gadget_owner`.
    drop(gadget_owner);

    // Despite dropping `gadget_owner`, we're still able to print out the name
    // of the `Owner` of the `Gadget`s. This is because we've only dropped a
    // single `Rc<Owner>`, not the `Owner` it points to. As long as there are
    // other `Rc<Owner>` values pointing at the same `Owner`, it will remain
    // allocated. The field projection `gadget1.owner.name` works because
    // `Rc<Owner>` automatically dereferences to `Owner`.
    println!("Gadget {} owned by {}", gadget1.id, gadget1.owner.name);
    println!("Gadget {} owned by {}", gadget2.id, gadget2.owner.name);

    // At the end of the function, `gadget1` and `gadget2` are destroyed, and
    // with them the last counted references to our `Owner`. Gadget Man now
    // gets destroyed as well.
}

Structs

Rc

A single-threaded reference-counting pointer.