Skip to content

Refactor alloc/rc.rs into separate files #81272

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
257 changes: 257 additions & 0 deletions library/alloc/src/rc/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,257 @@
#![stable(feature = "rust1", since = "1.0.0")]

//! Single-threaded reference-counting pointers. 'Rc' stands for 'Reference
//! Counted'.
//!
//! The type [`Rc<T>`][`Rc`] provides shared ownership of a value of type `T`,
//! allocated in the heap. Invoking [`clone`][clone] on [`Rc`] produces a new
//! pointer to the same allocation in the heap. When the last [`Rc`] pointer to a
//! given allocation is destroyed, the value stored in that allocation (often
//! referred to as "inner value") is also dropped.
//!
//! Shared references in Rust disallow mutation by default, and [`Rc`]
//! is no exception: you cannot generally obtain a mutable reference to
//! something inside an [`Rc`]. If you need mutability, put a [`Cell`]
//! or [`RefCell`] inside the [`Rc`]; see [an example of mutability
//! inside an `Rc`][mutability].
//!
//! [`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`][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`][arc].
//!
//! The [`downgrade`][downgrade] method can be used to create a non-owning
//! [`Weak`] pointer. A [`Weak`] pointer can be [`upgrade`][upgrade]d
//! to an [`Rc`], but this will return [`None`] if the value stored in the allocation has
//! already been dropped. In other words, `Weak` pointers do not keep the value
//! inside the allocation alive; however, they *do* keep the allocation
//! (the backing store for the inner value) alive.
//!
//! A cycle between [`Rc`] pointers will never be deallocated. For this reason,
//! [`Weak`] is used to break cycles. For example, a tree could have strong
//! [`Rc`] pointers from parent nodes to children, and [`Weak`] pointers from
//! children back to their parents.
//!
//! `Rc<T>` automatically dereferences to `T` (via the [`Deref`] trait),
//! so you can call `T`'s methods on a value of type [`Rc<T>`][`Rc`]. To avoid name
//! clashes with `T`'s methods, the methods of [`Rc<T>`][`Rc`] itself are associated
//! functions, called using [fully qualified syntax]:
//!
//! ```
//! use std::rc::Rc;
//!
//! let my_rc = Rc::new(());
//! Rc::downgrade(&my_rc);
//! ```
//!
//! `Rc<T>`'s implementations of traits like `Clone` may also be called using
//! fully qualified syntax. Some people prefer to use fully qualified syntax,
//! while others prefer using method-call syntax.
//!
//! ```
//! use std::rc::Rc;
//!
//! let rc = Rc::new(());
//! // Method-call syntax
//! let rc2 = rc.clone();
//! // Fully qualified syntax
//! let rc3 = Rc::clone(&rc);
//! ```
//!
//! [`Weak<T>`][`Weak`] does not auto-dereference to `T`, because the inner value may have
//! already been dropped.
//!
//! # Cloning references
//!
//! Creating a new reference to the same allocation as an existing reference counted pointer
//! is done using the `Clone` trait implemented for [`Rc<T>`][`Rc`] and [`Weak<T>`][`Weak`].
//!
//! ```
//! use std::rc::Rc;
//!
//! let foo = Rc::new(vec![1.0, 2.0, 3.0]);
//! // The two syntaxes below are equivalent.
//! let a = foo.clone();
//! let b = Rc::clone(&foo);
//! // a and b both point to the same memory location as foo.
//! ```
//!
//! The `Rc::clone(&from)` syntax is the most idiomatic because it conveys more explicitly
//! the meaning of the code. In the example above, this syntax makes it easier to see that
//! this code is creating a new reference rather than copying the whole content of foo.
//!
//! # 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 std::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>`
//! // gives us a new pointer to the same `Owner` allocation, incrementing
//! // the reference count in the process.
//! let gadget1 = Gadget {
//! id: 1,
//! owner: Rc::clone(&gadget_owner),
//! };
//! let gadget2 = Gadget {
//! id: 2,
//! owner: Rc::clone(&gadget_owner),
//! };
//!
//! // 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>` pointing at the same `Owner` allocation, it will remain
//! // live. 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.
//! }
//! ```
//!
//! If our requirements change, and we also need to be able to traverse from
//! `Owner` to `Gadget`, we will run into problems. An [`Rc`] pointer from `Owner`
//! to `Gadget` introduces a cycle. This means that their
//! reference counts can never reach 0, and the allocation will never be destroyed:
//! a memory leak. In order to get around this, we can use [`Weak`]
//! pointers.
//!
//! Rust actually makes it somewhat difficult to produce this loop in the first
//! place. In order to end up with two values that point at each other, one of
//! them needs to be mutable. This is difficult because [`Rc`] enforces
//! memory safety by only giving out shared references to the value it wraps,
//! and these don't allow direct mutation. We need to wrap the part of the
//! value we wish to mutate in a [`RefCell`], which provides *interior
//! mutability*: a method to achieve mutability through a shared reference.
//! [`RefCell`] enforces Rust's borrowing rules at runtime.
//!
//! ```
//! use std::rc::Rc;
//! use std::rc::Weak;
//! use std::cell::RefCell;
//!
//! struct Owner {
//! name: String,
//! gadgets: RefCell<Vec<Weak<Gadget>>>,
//! // ...other fields
//! }
//!
//! struct Gadget {
//! id: i32,
//! owner: Rc<Owner>,
//! // ...other fields
//! }
//!
//! fn main() {
//! // Create a reference-counted `Owner`. Note that we've put the `Owner`'s
//! // vector of `Gadget`s inside a `RefCell` so that we can mutate it through
//! // a shared reference.
//! let gadget_owner: Rc<Owner> = Rc::new(
//! Owner {
//! name: "Gadget Man".to_string(),
//! gadgets: RefCell::new(vec![]),
//! }
//! );
//!
//! // Create `Gadget`s belonging to `gadget_owner`, as before.
//! let gadget1 = Rc::new(
//! Gadget {
//! id: 1,
//! owner: Rc::clone(&gadget_owner),
//! }
//! );
//! let gadget2 = Rc::new(
//! Gadget {
//! id: 2,
//! owner: Rc::clone(&gadget_owner),
//! }
//! );
//!
//! // Add the `Gadget`s to their `Owner`.
//! {
//! let mut gadgets = gadget_owner.gadgets.borrow_mut();
//! gadgets.push(Rc::downgrade(&gadget1));
//! gadgets.push(Rc::downgrade(&gadget2));
//!
//! // `RefCell` dynamic borrow ends here.
//! }
//!
//! // Iterate over our `Gadget`s, printing their details out.
//! for gadget_weak in gadget_owner.gadgets.borrow().iter() {
//!
//! // `gadget_weak` is a `Weak<Gadget>`. Since `Weak` pointers can't
//! // guarantee the allocation still exists, we need to call
//! // `upgrade`, which returns an `Option<Rc<Gadget>>`.
//! //
//! // In this case we know the allocation still exists, so we simply
//! // `unwrap` the `Option`. In a more complicated program, you might
//! // need graceful error handling for a `None` result.
//!
//! let gadget = gadget_weak.upgrade().unwrap();
//! println!("Gadget {} owned by {}", gadget.id, gadget.owner.name);
//! }
//!
//! // At the end of the function, `gadget_owner`, `gadget1`, and `gadget2`
//! // are destroyed. There are now no strong (`Rc`) pointers to the
//! // gadgets, so they are destroyed. This zeroes the reference count on
//! // Gadget Man, so he gets destroyed as well.
//! }
//! ```
//!
//! [clone]: Clone::clone
//! [`Cell`]: core::cell::Cell
//! [`RefCell`]: core::cell::RefCell
//! [send]: core::marker::Send
//! [arc]: crate::sync::Arc
//! [`Deref`]: core::ops::Deref
//! [downgrade]: Rc::downgrade
//! [upgrade]: Weak::upgrade
//! [mutability]: core::cell#introducing-mutability-inside-of-something-immutable
//! [fully qualified syntax]: https://doc.rust-lang.org/book/ch19-03-advanced-traits.html#fully-qualified-syntax-for-disambiguation-calling-methods-with-the-same-name

mod rc;
mod utils;
mod weak;

#[cfg(test)]
mod tests;

#[stable(feature = "rust1", since = "1.0.0")]
pub use rc::Rc;
#[stable(feature = "rust1", since = "1.0.0")]
pub use weak::Weak;

pub(crate) use utils::{is_dangling, MarkerEq};
Loading