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
Rc
s 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 Rc
s. 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 Rc
s 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 Rc
s. 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);