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 Rc
s 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 Gadget
s are owned by a given Owner
.
We want to have our Gadget
s 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 Gadget
s,
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. |