1
Fork 0

Document liballoc::rc

This commit introduces a bunch of documentation, fixes some consistency
issues, and just basically brings Rc<T> and Weak<T> up to snuff.
This commit is contained in:
Steve Klabnik 2014-11-19 12:31:10 -05:00
parent 377d7524a8
commit a1d983aa16

View file

@ -8,27 +8,25 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
//! Task-local reference-counted boxes (the `Rc` type). //! Task-local reference-counted boxes (the `Rc<T>` type).
//! //!
//! The `Rc` type provides shared ownership of an immutable value. Destruction is //! The `Rc<T>` type provides shared ownership of an immutable value. Destruction is deterministic,
//! deterministic, and will occur as soon as the last owner is gone. It is marked //! and will occur as soon as the last owner is gone. It is marked as non-sendable because it
//! as non-sendable because it avoids the overhead of atomic reference counting. //! avoids the overhead of atomic reference counting.
//! //!
//! The `downgrade` method can be used to create a non-owning `Weak` pointer to the //! The `downgrade` method can be used to create a non-owning `Weak<T>` pointer to the box. A
//! box. A `Weak` pointer can be upgraded to an `Rc` pointer, but will return //! `Weak<T>` pointer can be upgraded to an `Rc<T>` pointer, but will return `None` if the value
//! `None` if the value has already been freed. //! has already been dropped.
//! //!
//! For example, a tree with parent pointers can be represented by putting the //! For example, a tree with parent pointers can be represented by putting the nodes behind strong
//! nodes behind strong `Rc` pointers, and then storing the parent pointers as //! `Rc<T>` pointers, and then storing the parent pointers as `Weak<T>` pointers.
//! `Weak` pointers.
//! //!
//! # Examples //! # Examples
//! //!
//! Consider a scenario where a set of `Gadget`s are owned by a given `Owner`. //! Consider a scenario where a set of `Gadget`s are owned by a given `Owner`. We want to have our
//! We want to have our `Gadget`s point to their `Owner`. We can't do this with //! `Gadget`s point to their `Owner`. We can't do this with unique ownership, because more than one
//! unique ownership, because more than one gadget may belong to the same //! gadget may belong to the same `Owner`. `Rc<T>` allows us to share an `Owner` between multiple
//! `Owner`. `Rc` allows us to share an `Owner` between multiple `Gadget`s, and //! `Gadget`s, and have the `Owner` remain allocated as long as any `Gadget` points at it.
//! have the `Owner` kept alive as long as any `Gadget` points at it.
//! //!
//! ```rust //! ```rust
//! use std::rc::Rc; //! use std::rc::Rc;
@ -51,7 +49,7 @@
//! ); //! );
//! //!
//! // Create Gadgets belonging to gadget_owner. To increment the reference //! // Create Gadgets belonging to gadget_owner. To increment the reference
//! // count we clone the Rc object. //! // count we clone the `Rc<T>` object.
//! let gadget1 = Gadget { id: 1, owner: gadget_owner.clone() }; //! let gadget1 = Gadget { id: 1, owner: gadget_owner.clone() };
//! let gadget2 = Gadget { id: 2, owner: gadget_owner.clone() }; //! let gadget2 = Gadget { id: 2, owner: gadget_owner.clone() };
//! //!
@ -60,8 +58,8 @@
//! // Despite dropping gadget_owner, we're still able to print out the name of //! // Despite dropping gadget_owner, we're still able to print out the name of
//! // the Owner of the Gadgets. This is because we've only dropped the //! // the Owner of the Gadgets. This is because we've only dropped the
//! // reference count object, not the Owner it wraps. As long as there are //! // reference count object, not the Owner it wraps. As long as there are
//! // other Rc objects pointing at the same Owner, it will stay alive. Notice //! // other `Rc<T>` objects pointing at the same Owner, it will remain allocated. Notice
//! // that the Rc wrapper around Gadget.owner gets automatically dereferenced //! // that the `Rc<T>` wrapper around Gadget.owner gets automatically dereferenced
//! // for us. //! // for us.
//! println!("Gadget {} owned by {}", gadget1.id, gadget1.owner.name); //! println!("Gadget {} owned by {}", gadget1.id, gadget1.owner.name);
//! println!("Gadget {} owned by {}", gadget2.id, gadget2.owner.name); //! println!("Gadget {} owned by {}", gadget2.id, gadget2.owner.name);
@ -72,23 +70,19 @@
//! } //! }
//! ``` //! ```
//! //!
//! If our requirements change, and we also need to be able to traverse from //! If our requirements change, and we also need to be able to traverse from Owner → Gadget, we
//! Owner → Gadget, we will run into problems: an `Rc` pointer from Owner → Gadget //! will run into problems: an `Rc<T>` pointer from Owner → Gadget introduces a cycle between the
//! introduces a cycle between the objects. This means that their reference counts //! objects. This means that their reference counts can never reach 0, and the objects will remain
//! can never reach 0, and the objects will stay alive: a memory leak. In order to //! allocated: a memory leak. In order to get around this, we can use `Weak<T>` pointers. These
//! get around this, we can use `Weak` pointers. These are reference counted //! pointers don't contribute to the total count.
//! pointers that don't keep an object alive if there are no normal `Rc` (or
//! *strong*) pointers left.
//! //!
//! Rust actually makes it somewhat difficult to produce this loop in the first //! Rust actually makes it somewhat difficult to produce this loop in the first place: in order to
//! place: in order to end up with two objects that point at each other, one of //! end up with two objects that point at each other, one of them needs to be mutable. This is
//! them needs to be mutable. This is problematic because `Rc` enforces memory //! problematic because `Rc<T>` enforces memory safety by only giving out shared references to the
//! safety by only giving out shared references to the object it wraps, and these //! object it wraps, and these don't allow direct mutation. We need to wrap the part of the object
//! don't allow direct mutation. We need to wrap the part of the object we wish to //! we wish to mutate in a `RefCell`, which provides *interior mutability*: a method to achieve
//! mutate in a `RefCell`, which provides *interior mutability*: a method to //! mutability through a shared reference. `RefCell` enforces Rust's borrowing rules at runtime.
//! achieve mutability through a shared reference. `RefCell` enforces Rust's //! Read the `Cell` documentation for more details on interior mutability.
//! borrowing rules at runtime. Read the `Cell` documentation for more details on
//! interior mutability.
//! //!
//! ```rust //! ```rust
//! use std::rc::Rc; //! use std::rc::Rc;
@ -131,7 +125,7 @@
//! for gadget_opt in gadget_owner.gadgets.borrow().iter() { //! for gadget_opt in gadget_owner.gadgets.borrow().iter() {
//! //!
//! // gadget_opt is a Weak<Gadget>. Since weak pointers can't guarantee //! // gadget_opt is a Weak<Gadget>. Since weak pointers can't guarantee
//! // that their object is still alive, we need to call upgrade() on them //! // that their object is still allocated, we need to call upgrade() on them
//! // to turn them into a strong reference. This returns an Option, which //! // to turn them into a strong reference. This returns an Option, which
//! // contains a reference to our object if it still exists. //! // contains a reference to our object if it still exists.
//! let gadget = gadget_opt.upgrade().unwrap(); //! let gadget = gadget_opt.upgrade().unwrap();
@ -139,7 +133,7 @@
//! } //! }
//! //!
//! // At the end of the method, gadget_owner, gadget1 and gadget2 get //! // At the end of the method, gadget_owner, gadget1 and gadget2 get
//! // destroyed. There are now no strong (Rc) references to the gadgets. //! // destroyed. There are now no strong (`Rc<T>`) references to the gadgets.
//! // Once they get destroyed, the Gadgets get destroyed. This zeroes the //! // Once they get destroyed, the Gadgets get destroyed. This zeroes the
//! // reference count on Gadget Man, so he gets destroyed as well. //! // reference count on Gadget Man, so he gets destroyed as well.
//! } //! }
@ -169,6 +163,8 @@ struct RcBox<T> {
} }
/// An immutable reference-counted pointer type. /// An immutable reference-counted pointer type.
///
/// See the [module level documentation](../index.html) for more.
#[unsafe_no_drop_flag] #[unsafe_no_drop_flag]
#[stable] #[stable]
pub struct Rc<T> { pub struct Rc<T> {
@ -180,7 +176,15 @@ pub struct Rc<T> {
} }
impl<T> Rc<T> { impl<T> Rc<T> {
/// Constructs a new reference-counted pointer. /// Constructs a new `Rc<T>`.
///
/// # Examples
///
/// ```
/// use std::rc::Rc;
///
/// let five = Rc::new(5i);
/// ```
#[stable] #[stable]
pub fn new(value: T) -> Rc<T> { pub fn new(value: T) -> Rc<T> {
unsafe { unsafe {
@ -201,7 +205,17 @@ impl<T> Rc<T> {
} }
} }
/// Downgrades the reference-counted pointer to a weak reference. /// Downgrades the `Rc<T>` to a `Weak<T>` reference.
///
/// # Examples
///
/// ```
/// use std::rc::Rc;
///
/// let five = Rc::new(5i);
///
/// let weak_five = five.downgrade();
/// ```
#[experimental = "Weak pointers may not belong in this module"] #[experimental = "Weak pointers may not belong in this module"]
pub fn downgrade(&self) -> Weak<T> { pub fn downgrade(&self) -> Weak<T> {
self.inc_weak(); self.inc_weak();
@ -223,27 +237,36 @@ pub fn weak_count<T>(this: &Rc<T>) -> uint { this.weak() - 1 }
#[experimental] #[experimental]
pub fn strong_count<T>(this: &Rc<T>) -> uint { this.strong() } pub fn strong_count<T>(this: &Rc<T>) -> uint { this.strong() }
/// Returns true if the `Rc` currently has unique ownership. /// Returns true if there are no other `Rc` or `Weak<T>` values that share the same inner value.
/// ///
/// Unique ownership means that there are no other `Rc` or `Weak` values /// # Examples
/// that share the same contents. ///
/// ```
/// use std::rc;
/// use std::rc::Rc;
///
/// let five = Rc::new(5i);
///
/// rc::is_unique(&five);
/// ```
#[inline] #[inline]
#[experimental] #[experimental]
pub fn is_unique<T>(rc: &Rc<T>) -> bool { pub fn is_unique<T>(rc: &Rc<T>) -> bool {
weak_count(rc) == 0 && strong_count(rc) == 1 weak_count(rc) == 0 && strong_count(rc) == 1
} }
/// Unwraps the contained value if the `Rc` has unique ownership. /// Unwraps the contained value if the `Rc<T>` is unique.
/// ///
/// If the `Rc` does not have unique ownership, `Err` is returned with the /// If the `Rc<T>` is not unique, an `Err` is returned with the same `Rc<T>`.
/// same `Rc`.
/// ///
/// # Example /// # Example
/// ///
/// ``` /// ```
/// use std::rc::{mod, Rc}; /// use std::rc::{mod, Rc};
///
/// let x = Rc::new(3u); /// let x = Rc::new(3u);
/// assert_eq!(rc::try_unwrap(x), Ok(3u)); /// assert_eq!(rc::try_unwrap(x), Ok(3u));
///
/// let x = Rc::new(4u); /// let x = Rc::new(4u);
/// let _y = x.clone(); /// let _y = x.clone();
/// assert_eq!(rc::try_unwrap(x), Err(Rc::new(4u))); /// assert_eq!(rc::try_unwrap(x), Err(Rc::new(4u)));
@ -266,18 +289,19 @@ pub fn try_unwrap<T>(rc: Rc<T>) -> Result<T, Rc<T>> {
} }
} }
/// Returns a mutable reference to the contained value if the `Rc` has /// Returns a mutable reference to the contained value if the `Rc<T>` is unique.
/// unique ownership.
/// ///
/// Returns `None` if the `Rc` does not have unique ownership. /// Returns `None` if the `Rc<T>` is not unique.
/// ///
/// # Example /// # Example
/// ///
/// ``` /// ```
/// use std::rc::{mod, Rc}; /// use std::rc::{mod, Rc};
///
/// let mut x = Rc::new(3u); /// let mut x = Rc::new(3u);
/// *rc::get_mut(&mut x).unwrap() = 4u; /// *rc::get_mut(&mut x).unwrap() = 4u;
/// assert_eq!(*x, 4u); /// assert_eq!(*x, 4u);
///
/// let _y = x.clone(); /// let _y = x.clone();
/// assert!(rc::get_mut(&mut x).is_none()); /// assert!(rc::get_mut(&mut x).is_none());
/// ``` /// ```
@ -293,11 +317,20 @@ pub fn get_mut<'a, T>(rc: &'a mut Rc<T>) -> Option<&'a mut T> {
} }
impl<T: Clone> Rc<T> { impl<T: Clone> Rc<T> {
/// Acquires a mutable pointer to the inner contents by guaranteeing that /// Make a mutable reference from the given `Rc<T>`.
/// the reference count is one (no sharing is possible).
/// ///
/// This is also referred to as a copy-on-write operation because the inner /// This is also referred to as a copy-on-write operation because the inner data is cloned if
/// data is cloned if the reference count is greater than one. /// the reference count is greater than one.
///
/// # Examples
///
/// ```
/// use std::rc::Rc;
///
/// let mut five = Rc::new(5i);
///
/// let mut_five = five.make_unique();
/// ```
#[inline] #[inline]
#[experimental] #[experimental]
pub fn make_unique(&mut self) -> &mut T { pub fn make_unique(&mut self) -> &mut T {
@ -307,8 +340,8 @@ impl<T: Clone> Rc<T> {
// This unsafety is ok because we're guaranteed that the pointer // This unsafety is ok because we're guaranteed that the pointer
// returned is the *only* pointer that will ever be returned to T. Our // returned is the *only* pointer that will ever be returned to T. Our
// reference count is guaranteed to be 1 at this point, and we required // reference count is guaranteed to be 1 at this point, and we required
// the Rc itself to be `mut`, so we're returning the only possible // the `Rc<T>` itself to be `mut`, so we're returning the only possible
// reference to the inner data. // reference to the inner value.
let inner = unsafe { &mut *self._ptr }; let inner = unsafe { &mut *self._ptr };
&mut inner.value &mut inner.value
} }
@ -316,7 +349,6 @@ impl<T: Clone> Rc<T> {
#[experimental = "Deref is experimental."] #[experimental = "Deref is experimental."]
impl<T> Deref<T> for Rc<T> { impl<T> Deref<T> for Rc<T> {
/// Borrows the value contained in the reference-counted pointer.
#[inline(always)] #[inline(always)]
fn deref(&self) -> &T { fn deref(&self) -> &T {
&self.inner().value &self.inner().value
@ -326,6 +358,30 @@ impl<T> Deref<T> for Rc<T> {
#[unsafe_destructor] #[unsafe_destructor]
#[experimental = "Drop is experimental."] #[experimental = "Drop is experimental."]
impl<T> Drop for Rc<T> { impl<T> Drop for Rc<T> {
/// Drops the `Rc<T>`.
///
/// This will decrement the strong reference count. If the strong reference count becomes zero
/// and the only other references are `Weak<T>` ones, `drop`s the inner value.
///
/// # Examples
///
/// ```
/// use std::rc::Rc;
///
/// {
/// let five = Rc::new(5i);
///
/// // stuff
///
/// drop(five); // explict drop
/// }
/// {
/// let five = Rc::new(5i);
///
/// // stuff
///
/// } // implicit drop
/// ```
fn drop(&mut self) { fn drop(&mut self) {
unsafe { unsafe {
if !self._ptr.is_null() { if !self._ptr.is_null() {
@ -349,6 +405,19 @@ impl<T> Drop for Rc<T> {
#[unstable = "Clone is unstable."] #[unstable = "Clone is unstable."]
impl<T> Clone for Rc<T> { impl<T> Clone for Rc<T> {
/// Makes a clone of the `Rc<T>`.
///
/// This increases the strong reference count.
///
/// # Examples
///
/// ```
/// use std::rc::Rc;
///
/// let five = Rc::new(5i);
///
/// five.clone();
/// ```
#[inline] #[inline]
fn clone(&self) -> Rc<T> { fn clone(&self) -> Rc<T> {
self.inc_strong(); self.inc_strong();
@ -358,6 +427,16 @@ impl<T> Clone for Rc<T> {
#[stable] #[stable]
impl<T: Default> Default for Rc<T> { impl<T: Default> Default for Rc<T> {
/// Creates a new `Rc<T>`, with the `Default` value for `T`.
///
/// # Examples
///
/// ```
/// use std::rc::Rc;
/// use std::default::Default;
///
/// let x: Rc<int> = Default::default();
/// ```
#[inline] #[inline]
fn default() -> Rc<T> { fn default() -> Rc<T> {
Rc::new(Default::default()) Rc::new(Default::default())
@ -366,8 +445,35 @@ impl<T: Default> Default for Rc<T> {
#[unstable = "PartialEq is unstable."] #[unstable = "PartialEq is unstable."]
impl<T: PartialEq> PartialEq for Rc<T> { impl<T: PartialEq> PartialEq for Rc<T> {
/// Equality for two `Rc<T>`s.
///
/// Two `Rc<T>`s are equal if their inner value are equal.
///
/// # Examples
///
/// ```
/// use std::rc::Rc;
///
/// let five = Rc::new(5i);
///
/// five == Rc::new(5i);
/// ```
#[inline(always)] #[inline(always)]
fn eq(&self, other: &Rc<T>) -> bool { **self == **other } fn eq(&self, other: &Rc<T>) -> bool { **self == **other }
/// Inequality for two `Rc<T>`s.
///
/// Two `Rc<T>`s are unequal if their inner value are unequal.
///
/// # Examples
///
/// ```
/// use std::rc::Rc;
///
/// let five = Rc::new(5i);
///
/// five != Rc::new(5i);
/// ```
#[inline(always)] #[inline(always)]
fn ne(&self, other: &Rc<T>) -> bool { **self != **other } fn ne(&self, other: &Rc<T>) -> bool { **self != **other }
} }
@ -377,26 +483,104 @@ impl<T: Eq> Eq for Rc<T> {}
#[unstable = "PartialOrd is unstable."] #[unstable = "PartialOrd is unstable."]
impl<T: PartialOrd> PartialOrd for Rc<T> { impl<T: PartialOrd> PartialOrd for Rc<T> {
/// Partial comparison for two `Rc<T>`s.
///
/// The two are compared by calling `partial_cmp()` on their inner values.
///
/// # Examples
///
/// ```
/// use std::rc::Rc;
///
/// let five = Rc::new(5i);
///
/// five.partial_cmp(&Rc::new(5i));
/// ```
#[inline(always)] #[inline(always)]
fn partial_cmp(&self, other: &Rc<T>) -> Option<Ordering> { fn partial_cmp(&self, other: &Rc<T>) -> Option<Ordering> {
(**self).partial_cmp(&**other) (**self).partial_cmp(&**other)
} }
/// Less-than comparison for two `Rc<T>`s.
///
/// The two are compared by calling `<` on their inner values.
///
/// # Examples
///
/// ```
/// use std::rc::Rc;
///
/// let five = Rc::new(5i);
///
/// five < Rc::new(5i);
/// ```
#[inline(always)] #[inline(always)]
fn lt(&self, other: &Rc<T>) -> bool { **self < **other } fn lt(&self, other: &Rc<T>) -> bool { **self < **other }
/// 'Less-than or equal to' comparison for two `Rc<T>`s.
///
/// The two are compared by calling `<=` on their inner values.
///
/// # Examples
///
/// ```
/// use std::rc::Rc;
///
/// let five = Rc::new(5i);
///
/// five <= Rc::new(5i);
/// ```
#[inline(always)] #[inline(always)]
fn le(&self, other: &Rc<T>) -> bool { **self <= **other } fn le(&self, other: &Rc<T>) -> bool { **self <= **other }
/// Greater-than comparison for two `Rc<T>`s.
///
/// The two are compared by calling `>` on their inner values.
///
/// # Examples
///
/// ```
/// use std::rc::Rc;
///
/// let five = Rc::new(5i);
///
/// five > Rc::new(5i);
/// ```
#[inline(always)] #[inline(always)]
fn gt(&self, other: &Rc<T>) -> bool { **self > **other } fn gt(&self, other: &Rc<T>) -> bool { **self > **other }
/// 'Greater-than or equal to' comparison for two `Rc<T>`s.
///
/// The two are compared by calling `>=` on their inner values.
///
/// # Examples
///
/// ```
/// use std::rc::Rc;
///
/// let five = Rc::new(5i);
///
/// five >= Rc::new(5i);
/// ```
#[inline(always)] #[inline(always)]
fn ge(&self, other: &Rc<T>) -> bool { **self >= **other } fn ge(&self, other: &Rc<T>) -> bool { **self >= **other }
} }
#[unstable = "Ord is unstable."] #[unstable = "Ord is unstable."]
impl<T: Ord> Ord for Rc<T> { impl<T: Ord> Ord for Rc<T> {
/// Comparison for two `Rc<T>`s.
///
/// The two are compared by calling `cmp()` on their inner values.
///
/// # Examples
///
/// ```
/// use std::rc::Rc;
///
/// let five = Rc::new(5i);
///
/// five.partial_cmp(&Rc::new(5i));
/// ```
#[inline] #[inline]
fn cmp(&self, other: &Rc<T>) -> Ordering { (**self).cmp(&**other) } fn cmp(&self, other: &Rc<T>) -> Ordering { (**self).cmp(&**other) }
} }
@ -408,7 +592,11 @@ impl<T: fmt::Show> fmt::Show for Rc<T> {
} }
} }
/// A weak reference to a reference-counted pointer. /// A weak version of `Rc<T>`.
///
/// Weak references do not count when determining if the inner value should be dropped.
///
/// See the [module level documentation](../index.html) for more.
#[unsafe_no_drop_flag] #[unsafe_no_drop_flag]
#[experimental = "Weak pointers may not belong in this module."] #[experimental = "Weak pointers may not belong in this module."]
pub struct Weak<T> { pub struct Weak<T> {
@ -423,8 +611,21 @@ pub struct Weak<T> {
impl<T> Weak<T> { impl<T> Weak<T> {
/// Upgrades a weak reference to a strong reference. /// Upgrades a weak reference to a strong reference.
/// ///
/// Returns `None` if there were no strong references and the data was /// Upgrades the `Weak<T>` reference to an `Rc<T>`, if possible.
/// destroyed. ///
/// Returns `None` if there were no strong references and the data was destroyed.
///
/// # Examples
///
/// ```
/// use std::rc::Rc;
///
/// let five = Rc::new(5i);
///
/// let weak_five = five.downgrade();
///
/// let strong_five: Option<Rc<_>> = weak_five.upgrade();
/// ```
pub fn upgrade(&self) -> Option<Rc<T>> { pub fn upgrade(&self) -> Option<Rc<T>> {
if self.strong() == 0 { if self.strong() == 0 {
None None
@ -438,6 +639,31 @@ impl<T> Weak<T> {
#[unsafe_destructor] #[unsafe_destructor]
#[experimental = "Weak pointers may not belong in this module."] #[experimental = "Weak pointers may not belong in this module."]
impl<T> Drop for Weak<T> { impl<T> Drop for Weak<T> {
/// Drops the `Weak<T>`.
///
/// This will decrement the weak reference count.
///
/// # Examples
///
/// ```
/// use std::rc::Rc;
///
/// {
/// let five = Rc::new(5i);
/// let weak_five = five.downgrade();
///
/// // stuff
///
/// drop(weak_five); // explict drop
/// }
/// {
/// let five = Rc::new(5i);
/// let weak_five = five.downgrade();
///
/// // stuff
///
/// } // implicit drop
/// ```
fn drop(&mut self) { fn drop(&mut self) {
unsafe { unsafe {
if !self._ptr.is_null() { if !self._ptr.is_null() {
@ -455,6 +681,19 @@ impl<T> Drop for Weak<T> {
#[experimental = "Weak pointers may not belong in this module."] #[experimental = "Weak pointers may not belong in this module."]
impl<T> Clone for Weak<T> { impl<T> Clone for Weak<T> {
/// Makes a clone of the `Weak<T>`.
///
/// This increases the weak reference count.
///
/// # Examples
///
/// ```
/// use std::rc::Rc;
///
/// let weak_five = Rc::new(5i).downgrade();
///
/// weak_five.clone();
/// ```
#[inline] #[inline]
fn clone(&self) -> Weak<T> { fn clone(&self) -> Weak<T> {
self.inc_weak(); self.inc_weak();