- Feature Name: strong_shared_ptr
- Start Date: 2017-08-28
- RFC PR: (leave this empty)
- Rust Issue: (leave this empty)
Summary
Add a version of Rc and Arc without weak counts.
Motivation
There are some situations where you want to use Rc and Arc for caching purposes. One such example is storing a string in a HashSet to avoid duplication of allocation (string interning). In such situations, and when caching a lot of data, you pay an unnecessary std::mem::size_of::<usize>() cost on the heap, making the abstraction a non-zero cost one.
This also makes .clone() somewhat cheaper - which while probably always negligible in the case of Rc can have some measurable effect when it comes to Arc.
Such strong-only smart pointers, hence StrongRc and StrongArc, could be implemented in a crate. However, as of 2017-08-28, the implementations of Arc and Rc require a lot of unstable features making the use of such a crate in stable Rust only possible far into the future.
Detailed design
Take the implementations of Rc and Arc and remove all logic pertaining to the weak count.
Name the new types StrongRc and StrongArc. Alternative possible names are StrongOnlyRc and StrongOnlyArc to avoid confusion with the strong counterparts of std::rc::Weak and std::sync::Weak.
How We Teach This
Teach it as Rc and Arc but negate the teachings pertaining to the weak count. A note should be added that for tree-like data structures, and other cyclical data structures, Rc and Arc should be used instead.
Drawbacks
- Bloating the size of the standard library.
Alternatives
- Work on stabilizing the features needed to implement this in a crate.
- Add a version of
Arc and Rc bitmasking the strong and weak counts into a single usize.
- Add a type parameter
C: Add<Output = C> + ... to Rc, RcBox and Arc, ArcInner defaulting to usize thereby enabling C = u32, which fit into 8 bytes together. This is essentially the same as bitmasking but less manual.
- Add a type parameter
W: RcWeakMode / W: ArcWeakMode which governs if Rc / Arc are WithWeak mode or NoWeak mode respectively. Strong and weak interaction logic is moved into WithWeak. The std::mem::size_of::<NoWeak> is 0. The benefit of this is less code bloat - the downside is potentially lower teachability - however, on the documentation of NoWeak the documentation details should still be providable.
struct RcBox<T: ?Sized, W : RcWeakMode = WithWeak> {
strong: Cell<usize>,
weak: W,
value: T,
}
// or, maybe:
struct RcBox<T: ?Sized, W: RcWeakMode<T> = WithWeak<T>> {
strong: Cell<usize>,
weak: W,
value: T,
}
Unresolved questions
None, as of yet.