[][src]Struct cactusref::Rc

pub struct Rc<T: ?Sized> { /* fields omitted */ }

A single-threaded reference-counting pointer. 'Rc' stands for 'Reference Counted'.

This Rc differs from the Rc in std by adding support for detecting and deallocating orphaned cycles of references. An orphaned cycle is one in which all objects are only owned by other members of the cycle.

See the module-level documentation for more details.

The inherent methods of Rc are all associated functions, which means that you have to call them as e.g., Rc::get_mut(&mut value) instead of value.get_mut(). This avoids conflicts with methods of the inner type T.

Like std::rc::Rc, Rc is !Send and !Sync.

This example deliberately fails to compile
fn requires_send<T: Send>(s: T) {}
requires_send(Rc::new(5));
This example deliberately fails to compile
fn requires_sync<T: Sync>(s: T) {}
requires_sync(Rc::new(5));

Methods

impl<T> Rc<T>[src]

pub fn new(value: T) -> Self[src]

Constructs a new Rc<T>.

Examples

use cactusref::Rc;

let five = Rc::new(5);

pub fn pin(value: T) -> Pin<Self>[src]

Constructs a new Pin<Rc<T>>. If T does not implement Unpin, then value will be pinned in memory and unable to be moved.

pub fn try_unwrap(this: Self) -> Result<T, Self>[src]

Returns the contained value, if the Rc has exactly one strong reference.

Otherwise, an Err is returned with the same Rc that was passed in.

This will succeed even if there are outstanding weak references.

Examples

use cactusref::Rc;

let x = Rc::new(3);
assert_eq!(Rc::try_unwrap(x), Ok(3));

let x = Rc::new(4);
let _y = Rc::clone(&x);
assert_eq!(*Rc::try_unwrap(x).unwrap_err(), 4);

impl<T: ?Sized> Rc<T>[src]

pub fn into_raw(this: Self) -> *const T[src]

Consumes the Rc, returning the wrapped pointer.

To avoid a memory leak the pointer must be converted back to an Rc using Rc::from_raw.

Examples

use cactusref::Rc;

let x = Rc::new("hello".to_owned());
let x_ptr = Rc::into_raw(x);
assert_eq!(unsafe { &*x_ptr }, "hello");

pub unsafe fn from_raw(ptr: *const T) -> Self[src]

Constructs an Rc from a raw pointer.

The raw pointer must have been previously returned by a call to a Rc::into_raw.

This function is unsafe because improper use may lead to memory problems. For example, a double-free may occur if the function is called twice on the same raw pointer.

Examples

use cactusref::Rc;

let x = Rc::new("hello".to_owned());
let x_ptr = Rc::into_raw(x);

unsafe {
    // Convert back to an `Rc` to prevent leak.
    let x = Rc::from_raw(x_ptr);
    assert_eq!(&*x, "hello");

    // Further calls to `Self::from_raw(x_ptr)` would be memory unsafe.
}

// The memory was freed when `x` went out of scope above, so `x_ptr` is now dangling!

pub fn into_raw_non_null(this: Self) -> NonNull<T>[src]

Consumes the Rc, returning the wrapped pointer as NonNull<T>.

Examples

use cactusref::Rc;

let x = Rc::new("hello".to_owned());
let ptr = Rc::into_raw_non_null(x);
let deref = unsafe { ptr.as_ref() };
assert_eq!(deref, "hello");

pub fn downgrade(this: &Self) -> Weak<T>[src]

Creates a new Weak pointer to this value.

Examples

use cactusref::Rc;

let five = Rc::new(5);

let weak_five = Rc::downgrade(&five);

pub fn weak_count(this: &Self) -> usize[src]

Gets the number of Weak pointers to this value.

Examples

use cactusref::Rc;

let five = Rc::new(5);
let _weak_five = Rc::downgrade(&five);

assert_eq!(1, Rc::weak_count(&five));

pub fn strong_count(this: &Self) -> usize[src]

Gets the number of strong (Rc) pointers to this value.

Examples

use cactusref::Rc;

let five = Rc::new(5);
let _also_five = Rc::clone(&five);

assert_eq!(2, Rc::strong_count(&five));

pub fn get_mut(this: &mut Self) -> Option<&mut T>[src]

Returns a mutable reference to the inner value, if there are no other Rc or Weak pointers to the same value.

Returns None otherwise, because it is not safe to mutate a shared value.

See also make_mut, which will clone the inner value when it's shared.

Examples

use cactusref::Rc;

let mut x = Rc::new(3);
*Rc::get_mut(&mut x).unwrap() = 4;
assert_eq!(*x, 4);

let _y = Rc::clone(&x);
assert!(Rc::get_mut(&mut x).is_none());

pub fn ptr_eq(this: &Self, other: &Self) -> bool[src]

Returns true if the two Rcs point to the same value (not just values that compare as equal).

Examples

use cactusref::Rc;

let five = Rc::new(5);
let same_five = Rc::clone(&five);
let other_five = Rc::new(5);

assert!(Rc::ptr_eq(&five, &same_five));
assert!(!Rc::ptr_eq(&five, &other_five));

impl<T: Clone> Rc<T>[src]

pub fn make_mut(this: &mut Self) -> &mut T[src]

Makes a mutable reference into the given Rc.

If there are other Rc pointers to the same value, then make_mut will clone the inner value to ensure unique ownership. This is also referred to as clone-on-write.

If there are no other Rc pointers to this value, then Weak pointers to this value will be dissassociated.

See also get_mut, which will fail rather than cloning.

Examples

use cactusref::Rc;

let mut data = Rc::new(5);

*Rc::make_mut(&mut data) += 1;        // Won't clone anything
let mut other_data = Rc::clone(&data);    // Won't clone inner data
*Rc::make_mut(&mut data) += 1;        // Clones inner data
*Rc::make_mut(&mut data) += 1;        // Won't clone anything
*Rc::make_mut(&mut other_data) *= 2;  // Won't clone anything

// Now `data` and `other_data` point to different values.
assert_eq!(*data, 8);
assert_eq!(*other_data, 12);

Weak pointers will be dissassociated:

use cactusref::Rc;

let mut data = Rc::new(75);
let weak = Rc::downgrade(&data);

assert!(75 == *data);
assert!(75 == *weak.upgrade().unwrap());

*Rc::make_mut(&mut data) += 1;

assert!(76 == *data);
assert!(weak.upgrade().is_none());

Trait Implementations

impl<T: ?Sized> Adoptable for Rc<T>[src]

Implementation of Adoptable for Rc which enables Rcs to form a cycle of strong references that are reaped by Rc's Drop implementation.

unsafe fn adopt(this: &Self, other: &Self)[src]

Perform bookkeeping to record that this holds an owned reference to other.

Drop expects that this currently holds a refernce to other by the time adopt is called, although it may be safe to call adopt before the reference is held.

⚠️ Safety

CactusRef relies on proper use of Adoptable::adopt and Adoptable::unadopt to maintain bookkeeping about the object graph for breaking cycles. These functions are unsafe because improperly managing the bookkeeping can cause the Rc Drop implementation to deallocate cycles while they are still externally reachable. All held Rcs that point to members of the now deallocated cycle will dangle.

CactusRef makes a best-effort attempt to abort the program if an access to a dangling Rc occurs.

Examples

The following implements a self-referential array.

use cactusref::{Adoptable, Rc};
use std::cell::RefCell;

#[derive(Default)]
struct Array {
    buffer: Vec<Rc<RefCell<Self>>>,
}

let array = Rc::new(RefCell::new(Array::default()));
for _ in 0..10 {
    let item = Rc::clone(&array);
    array.borrow_mut().buffer.push(item);
    unsafe {
        Rc::adopt(&array, &array);
    }
}
let weak = Rc::downgrade(&array);
// 1 for the array binding, 10 for the `Rc`s in buffer
assert_eq!(Rc::strong_count(&array), 11);
drop(array);
assert!(weak.upgrade().is_none());
assert_eq!(weak.weak_count(), Some(1));

unsafe fn unadopt(this: &Self, other: &Self)[src]

Perform bookkeeping to record that this no longer holds an owned reference to other.

Drop expects that this currently does not hold a refernce to other by the time unadopt is called, although it may be safe to call adopt before the reference is held.

⚠️ Safety

CactusRef relies on proper use of Adoptable::adopt and Adoptable::unadopt to maintain bookkeeping about the object graph for breaking cycles. These functions are unsafe because improperly managing the bookkeeping can cause the Rc Drop implementation to deallocate cycles while they are still externally reachable. All held Rcs that point to members of the now deallocated cycle will dangle.

CactusRef makes a best-effort attempt to abort the program if an access to a dangling Rc occurs.

Examples

The following implements a self-referential array.

use cactusref::{Adoptable, Rc};
use std::cell::RefCell;

#[derive(Default)]
struct Array {
    buffer: Vec<Rc<RefCell<Self>>>,
}

let array = Rc::new(RefCell::new(Array::default()));
for _ in 0..10 {
    let item = Rc::clone(&array);
    array.borrow_mut().buffer.push(item);
    unsafe {
        Rc::adopt(&array, &array);
    }
}
let weak = Rc::downgrade(&array);
// 1 for the array binding, 10 for the `Rc`s in buffer
assert_eq!(Rc::strong_count(&array), 11);
let head = array.borrow_mut().buffer.pop().unwrap();
unsafe {
    Rc::unadopt(&array, &head);
}
drop(head);
assert_eq!(Rc::strong_count(&array), 10);
drop(array);
assert!(weak.upgrade().is_none());
assert_eq!(weak.weak_count(), Some(1));

impl<T: ?Sized + PartialOrd> PartialOrd<Rc<T>> for Rc<T>[src]

fn partial_cmp(&self, other: &Self) -> Option<Ordering>[src]

Partial comparison for two Rcs.

The two are compared by calling partial_cmp() on their inner values.

Examples

use cactusref::Rc;
use std::cmp::Ordering;

let five = Rc::new(5);

assert_eq!(Some(Ordering::Less), five.partial_cmp(&Rc::new(6)));

fn lt(&self, other: &Self) -> bool[src]

Less-than comparison for two Rcs.

The two are compared by calling < on their inner values.

Examples

use cactusref::Rc;

let five = Rc::new(5);

assert!(five < Rc::new(6));

fn le(&self, other: &Self) -> bool[src]

'Less than or equal to' comparison for two Rcs.

The two are compared by calling <= on their inner values.

Examples

use cactusref::Rc;

let five = Rc::new(5);

assert!(five <= Rc::new(5));

fn gt(&self, other: &Self) -> bool[src]

Greater-than comparison for two Rcs.

The two are compared by calling > on their inner values.

Examples

use cactusref::Rc;

let five = Rc::new(5);

assert!(five > Rc::new(4));

fn ge(&self, other: &Self) -> bool[src]

'Greater than or equal to' comparison for two Rcs.

The two are compared by calling >= on their inner values.

Examples

use cactusref::Rc;

let five = Rc::new(5);

assert!(five >= Rc::new(5));

impl<T: ?Sized + Eq> Eq for Rc<T>[src]

impl<T> From<T> for Rc<T>[src]

impl<'_, T: Clone> From<&'_ [T]> for Rc<[T]>[src]

impl<'_> From<&'_ str> for Rc<str>[src]

impl From<String> for Rc<str>[src]

impl<T: ?Sized> From<Box<T>> for Rc<T>[src]

impl<T> From<Vec<T>> for Rc<[T]>[src]

impl<T: ?Sized> AsRef<T> for Rc<T>[src]

impl<T: ?Sized + PartialEq> PartialEq<Rc<T>> for Rc<T>[src]

fn eq(&self, other: &Self) -> bool[src]

Equality for two Rcs.

Two Rcs are equal if their inner values are equal.

If T also implements Eq, two Rcs that point to the same value are always equal.

Examples

use cactusref::Rc;

let five = Rc::new(5);

assert!(five == Rc::new(5));

fn ne(&self, other: &Self) -> bool[src]

Inequality for two Rcs.

Two Rcs are unequal if their inner values are unequal.

If T also implements Eq, two Rcs that point to the same value are never unequal.

Examples

use cactusref::Rc;

let five = Rc::new(5);

assert!(five != Rc::new(6));

impl<T: ?Sized> Drop for Rc<T>[src]

fn drop(&mut self)[src]

Drops the Rc.

This will decrement the strong reference count. If the strong reference count reaches zero then the only other references (if any) are Weak, so we drop the inner value.

If this Rc has adopted any other Rcs, drop will trace the reachable object graph and detect if this Rc is part of an orphaned cycle. An orphaned cycle is a cycle in which all members have no owned references held by Rcs outside of the cycle.

Cycle detection is a zero-cost abstraction. Rcs do not pay the cost of the reachability check unless they use Adoptable::adopt.

Examples

use cactusref::Rc;

struct Foo;

impl Drop for Foo {
    fn drop(&mut self) {
        println!("dropped!");
    }
}

let foo  = Rc::new(Foo);
let foo2 = Rc::clone(&foo);

drop(foo);    // Doesn't print anything
drop(foo2);   // Prints "dropped!"
use cactusref::{Adoptable, Rc};

struct Foo(u8);

impl Drop for Foo {
    fn drop(&mut self) {
        println!("dropped {}!", self.0);
    }
}

let foo  = Rc::new(Foo(10));
let foo2 = Rc::new(Foo(20));

unsafe {
    Rc::adopt(&foo, &foo2);
    Rc::adopt(&foo2, &foo);
}

drop(foo);    // Doesn't print anything
drop(foo2);   // Prints "dropped 10!" and "dropped 20!"

Cycle Detection and Deallocation Algorithm

Rc::adopt does explicit bookkeeping to store links to adoptee Rcs. These links form a graph of reachable objects which are used to detect cycles.

On drop, if an Rc has no links, it is dropped like a normal Rc. If the Rc has links, Drop performs a breadth first search by traversing the forward and backward links stored in each Rc. Deallocating cycles requires correct use of Adoptable::adopt and Adoptable::unadopt to perform the reachability bookkeeping.

After determining all reachable objects, Rc reduces the graph to objects that form a cycle by performing pairwise reachability checks. During this step, for each object in the cycle, Rc counts the number of refs held by other objects in the cycle.

Using the cycle-held references, Rc computes whether the object graph is reachable by any non-cycle nodes by comparing strong counts.

If the cycle is orphaned, Rc busts all the link structures and deallocates each object.

Performance

Cycle detection uses breadth first search to trace the object graph. The runtime complexity of detecting a cycle is O(links + nodes) where links is the number of adoptions that are alive and nodes is the number of objects in the cycle.

Determining whether the cycle is orphaned builds on cycle detection and iterates over all nodes in the graph to see if their strong count is greater than the number of references in the cycle. The runtime complexity of finding an orphaned cycle is O(links + nodes) where links is the number of adoptions that are alive and nodes is the number objects in the cycle.

impl<T: ?Sized> Clone for Rc<T>[src]

fn clone(&self) -> Self[src]

Makes a clone of the Rc pointer.

This creates another pointer to the same inner value, increasing the strong reference count.

Examples

use cactusref::Rc;

let five = Rc::new(5);

let _ = Rc::clone(&five);

fn clone_from(&mut self, source: &Self)1.0.0[src]

Performs copy-assignment from source. Read more

impl<T: ?Sized> Unpin for Rc<T>[src]

impl<T: ?Sized + Ord> Ord for Rc<T>[src]

fn cmp(&self, other: &Self) -> Ordering[src]

Comparison for two Rcs.

The two are compared by calling cmp() on their inner values.

Examples

use cactusref::Rc;
use std::cmp::Ordering;

let five = Rc::new(5);

assert_eq!(Ordering::Less, five.cmp(&Rc::new(6)));

fn max(self, other: Self) -> Self1.21.0[src]

Compares and returns the maximum of two values. Read more

fn min(self, other: Self) -> Self1.21.0[src]

Compares and returns the minimum of two values. Read more

fn clamp(self, min: Self, max: Self) -> Self[src]

🔬 This is a nightly-only experimental API. (clamp)

Restrict a value to a certain interval. Read more

impl<T: Default> Default for Rc<T>[src]

fn default() -> Self[src]

Creates a new Rc<T>, with the Default value for T.

Examples

use cactusref::Rc;

let x: Rc<i32> = Default::default();
assert_eq!(*x, 0);

impl<T: ?Sized + Display> Display for Rc<T>[src]

impl<T: ?Sized + Debug> Debug for Rc<T>[src]

impl<T: ?Sized> Deref for Rc<T>[src]

type Target = T

The resulting type after dereferencing.

impl<T: ?Sized + Hash> Hash for Rc<T>[src]

fn hash_slice<H>(data: &[Self], state: &mut H) where
    H: Hasher
1.3.0[src]

Feeds a slice of this type into the given [Hasher]. Read more

impl<T: ?Sized> Pointer for Rc<T>[src]

impl<T: ?Sized> Borrow<T> for Rc<T>[src]

Auto Trait Implementations

impl<T> !Send for Rc<T>

impl<T> !Sync for Rc<T>

impl<T> !UnwindSafe for Rc<T>

impl<T> !RefUnwindSafe for Rc<T>

Blanket Implementations

impl<T> From<T> for T[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

impl<T> ToString for T where
    T: Display + ?Sized
[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> Any for T where
    T: 'static + ?Sized
[src]