Trait cactusref::Adopt[][src]

pub unsafe trait Adopt: Sealed {
    unsafe fn adopt(this: &Self, other: &Self);
unsafe fn unadopt(this: &Self, other: &Self); }
Expand description

Build a graph of linked Rc smart pointers to enable busting cycles on drop.

Calling adopt builds an object graph which can be used by to detect cycles.

Safety

Implementors of this trait must ensure that bookkeeping edges in the object graph is correct because these links are used to determine whether an Rc is reachable in Rc’s Drop implementation. Failure to properly bookkeep the object graph will result in undefined behavior.

Undefined behavior may include:

  • Memory leaks.
  • Double-frees.
  • Dangling Rcs which will cause a use after free.`

Required methods

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

Adoption is a one-way link, or a directed edge in the object graph which means “this owns other”.

adopt can be called multiple times for a pair of Rcs. Each call to adopt indicates that this owns one distinct clone of other.

This is an associated function that needs to be used as Adopt::adopt(...). A method would interfere with methods of the same name on the contents of a Rc used through Deref.

Safety

Callers must ensure that this owns a strong reference to other.

Callers must call unadopt when this no longer holds a strong reference to other.

Perform bookkeeping to record that this has removed an owned reference to other.

Adoption is a one-way link, or a directed edge in the object graph which means “this owns other”.

This is an associated function that needs to be used as Adopt::unadopt(...). A method would interfere with methods of the same name on the contents of a Rc used through Deref.

Safety

Callers must ensure that this has removed an owned reference to other.

For each call to Adopt::unadopt(&this, &other), callers must ensure that a matching call was made to Adopt::adopt(&this, &other).

Implementors

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

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

Adoption is a one-way link, or a directed edge in the object graph which means “this owns other”.

adopt can be called multiple times for a pair of Rcs. Each call to adopt indicates that this owns one distinct clone of other.

This is an associated function that needs to be used as Rc::adopt(...). A method would interfere with methods of the same name on the contents of a Rc used through Deref.

Safety

Callers must ensure that this owns a strong reference to other.

Callers must call unadopt when this no longer holds a strong reference to other.

Calling adopt does not increment the strong count of other. Callers must ensure that other has been cloned and stored in the T contained by this.

Examples

The following implements a self-referential array.

use cactusref::{Adopt, 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);
    unsafe {
        Rc::adopt(&array, &item);
    }
    array.borrow_mut().buffer.push(item);
}
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(), 0);

Perform bookkeeping to record that this has removed an owned reference to other.

Adoption is a one-way link, or a directed edge in the object graph which means “this owns other”.

This is an associated function that needs to be used as Adopt::unadopt(...). A method would interfere with methods of the same name on the contents of a Rc used through Deref.

Safety

Callers must ensure that this has removed an owned reference to other.

For each call to Adopt::unadopt(&this, &other), callers must ensure that a matching call was made to Adopt::adopt(&this, &other).

This crate 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::{Adopt, 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);
    unsafe {
        Rc::adopt(&array, &item);
    }
    array.borrow_mut().buffer.push(item);
}
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(), 0);