Skip to content

Commit 65bbb3d

Browse files
yoshuawuytsKodrAus
andcommitted
Refactor alloc/rc.rs into separate files
- `alloc::rc::Rc` now lives in `libraries/alloc/rc/rc.rs` - `alloc::rc::Weak` now lives in `libraries/alloc/rc/weak.rs` - the majority of tests now live in `alloc/tests/arc.rs` - one test which tests internals is in `alloc/rc/rc.rs` Other changes: - Remove trailing newline - Remove unused re-exports - Fix rc re-exports Co-Authored-By: Ashley Mannix <kodraus@hey.com>
1 parent 301ad8a commit 65bbb3d

File tree

7 files changed

+1356
-1308
lines changed

7 files changed

+1356
-1308
lines changed

library/alloc/src/rc/mod.rs

+257
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,257 @@
1+
#![stable(feature = "rust1", since = "1.0.0")]
2+
3+
//! Single-threaded reference-counting pointers. 'Rc' stands for 'Reference
4+
//! Counted'.
5+
//!
6+
//! The type [`Rc<T>`][`Rc`] provides shared ownership of a value of type `T`,
7+
//! allocated in the heap. Invoking [`clone`][clone] on [`Rc`] produces a new
8+
//! pointer to the same allocation in the heap. When the last [`Rc`] pointer to a
9+
//! given allocation is destroyed, the value stored in that allocation (often
10+
//! referred to as "inner value") is also dropped.
11+
//!
12+
//! Shared references in Rust disallow mutation by default, and [`Rc`]
13+
//! is no exception: you cannot generally obtain a mutable reference to
14+
//! something inside an [`Rc`]. If you need mutability, put a [`Cell`]
15+
//! or [`RefCell`] inside the [`Rc`]; see [an example of mutability
16+
//! inside an `Rc`][mutability].
17+
//!
18+
//! [`Rc`] uses non-atomic reference counting. This means that overhead is very
19+
//! low, but an [`Rc`] cannot be sent between threads, and consequently [`Rc`]
20+
//! does not implement [`Send`][send]. As a result, the Rust compiler
21+
//! will check *at compile time* that you are not sending [`Rc`]s between
22+
//! threads. If you need multi-threaded, atomic reference counting, use
23+
//! [`sync::Arc`][arc].
24+
//!
25+
//! The [`downgrade`][downgrade] method can be used to create a non-owning
26+
//! [`Weak`] pointer. A [`Weak`] pointer can be [`upgrade`][upgrade]d
27+
//! to an [`Rc`], but this will return [`None`] if the value stored in the allocation has
28+
//! already been dropped. In other words, `Weak` pointers do not keep the value
29+
//! inside the allocation alive; however, they *do* keep the allocation
30+
//! (the backing store for the inner value) alive.
31+
//!
32+
//! A cycle between [`Rc`] pointers will never be deallocated. For this reason,
33+
//! [`Weak`] is used to break cycles. For example, a tree could have strong
34+
//! [`Rc`] pointers from parent nodes to children, and [`Weak`] pointers from
35+
//! children back to their parents.
36+
//!
37+
//! `Rc<T>` automatically dereferences to `T` (via the [`Deref`] trait),
38+
//! so you can call `T`'s methods on a value of type [`Rc<T>`][`Rc`]. To avoid name
39+
//! clashes with `T`'s methods, the methods of [`Rc<T>`][`Rc`] itself are associated
40+
//! functions, called using [fully qualified syntax]:
41+
//!
42+
//! ```
43+
//! use std::rc::Rc;
44+
//!
45+
//! let my_rc = Rc::new(());
46+
//! Rc::downgrade(&my_rc);
47+
//! ```
48+
//!
49+
//! `Rc<T>`'s implementations of traits like `Clone` may also be called using
50+
//! fully qualified syntax. Some people prefer to use fully qualified syntax,
51+
//! while others prefer using method-call syntax.
52+
//!
53+
//! ```
54+
//! use std::rc::Rc;
55+
//!
56+
//! let rc = Rc::new(());
57+
//! // Method-call syntax
58+
//! let rc2 = rc.clone();
59+
//! // Fully qualified syntax
60+
//! let rc3 = Rc::clone(&rc);
61+
//! ```
62+
//!
63+
//! [`Weak<T>`][`Weak`] does not auto-dereference to `T`, because the inner value may have
64+
//! already been dropped.
65+
//!
66+
//! # Cloning references
67+
//!
68+
//! Creating a new reference to the same allocation as an existing reference counted pointer
69+
//! is done using the `Clone` trait implemented for [`Rc<T>`][`Rc`] and [`Weak<T>`][`Weak`].
70+
//!
71+
//! ```
72+
//! use std::rc::Rc;
73+
//!
74+
//! let foo = Rc::new(vec![1.0, 2.0, 3.0]);
75+
//! // The two syntaxes below are equivalent.
76+
//! let a = foo.clone();
77+
//! let b = Rc::clone(&foo);
78+
//! // a and b both point to the same memory location as foo.
79+
//! ```
80+
//!
81+
//! The `Rc::clone(&from)` syntax is the most idiomatic because it conveys more explicitly
82+
//! the meaning of the code. In the example above, this syntax makes it easier to see that
83+
//! this code is creating a new reference rather than copying the whole content of foo.
84+
//!
85+
//! # Examples
86+
//!
87+
//! Consider a scenario where a set of `Gadget`s are owned by a given `Owner`.
88+
//! We want to have our `Gadget`s point to their `Owner`. We can't do this with
89+
//! unique ownership, because more than one gadget may belong to the same
90+
//! `Owner`. [`Rc`] allows us to share an `Owner` between multiple `Gadget`s,
91+
//! and have the `Owner` remain allocated as long as any `Gadget` points at it.
92+
//!
93+
//! ```
94+
//! use std::rc::Rc;
95+
//!
96+
//! struct Owner {
97+
//! name: String,
98+
//! // ...other fields
99+
//! }
100+
//!
101+
//! struct Gadget {
102+
//! id: i32,
103+
//! owner: Rc<Owner>,
104+
//! // ...other fields
105+
//! }
106+
//!
107+
//! fn main() {
108+
//! // Create a reference-counted `Owner`.
109+
//! let gadget_owner: Rc<Owner> = Rc::new(
110+
//! Owner {
111+
//! name: "Gadget Man".to_string(),
112+
//! }
113+
//! );
114+
//!
115+
//! // Create `Gadget`s belonging to `gadget_owner`. Cloning the `Rc<Owner>`
116+
//! // gives us a new pointer to the same `Owner` allocation, incrementing
117+
//! // the reference count in the process.
118+
//! let gadget1 = Gadget {
119+
//! id: 1,
120+
//! owner: Rc::clone(&gadget_owner),
121+
//! };
122+
//! let gadget2 = Gadget {
123+
//! id: 2,
124+
//! owner: Rc::clone(&gadget_owner),
125+
//! };
126+
//!
127+
//! // Dispose of our local variable `gadget_owner`.
128+
//! drop(gadget_owner);
129+
//!
130+
//! // Despite dropping `gadget_owner`, we're still able to print out the name
131+
//! // of the `Owner` of the `Gadget`s. This is because we've only dropped a
132+
//! // single `Rc<Owner>`, not the `Owner` it points to. As long as there are
133+
//! // other `Rc<Owner>` pointing at the same `Owner` allocation, it will remain
134+
//! // live. The field projection `gadget1.owner.name` works because
135+
//! // `Rc<Owner>` automatically dereferences to `Owner`.
136+
//! println!("Gadget {} owned by {}", gadget1.id, gadget1.owner.name);
137+
//! println!("Gadget {} owned by {}", gadget2.id, gadget2.owner.name);
138+
//!
139+
//! // At the end of the function, `gadget1` and `gadget2` are destroyed, and
140+
//! // with them the last counted references to our `Owner`. Gadget Man now
141+
//! // gets destroyed as well.
142+
//! }
143+
//! ```
144+
//!
145+
//! If our requirements change, and we also need to be able to traverse from
146+
//! `Owner` to `Gadget`, we will run into problems. An [`Rc`] pointer from `Owner`
147+
//! to `Gadget` introduces a cycle. This means that their
148+
//! reference counts can never reach 0, and the allocation will never be destroyed:
149+
//! a memory leak. In order to get around this, we can use [`Weak`]
150+
//! pointers.
151+
//!
152+
//! Rust actually makes it somewhat difficult to produce this loop in the first
153+
//! place. In order to end up with two values that point at each other, one of
154+
//! them needs to be mutable. This is difficult because [`Rc`] enforces
155+
//! memory safety by only giving out shared references to the value it wraps,
156+
//! and these don't allow direct mutation. We need to wrap the part of the
157+
//! value we wish to mutate in a [`RefCell`], which provides *interior
158+
//! mutability*: a method to achieve mutability through a shared reference.
159+
//! [`RefCell`] enforces Rust's borrowing rules at runtime.
160+
//!
161+
//! ```
162+
//! use std::rc::Rc;
163+
//! use std::rc::Weak;
164+
//! use std::cell::RefCell;
165+
//!
166+
//! struct Owner {
167+
//! name: String,
168+
//! gadgets: RefCell<Vec<Weak<Gadget>>>,
169+
//! // ...other fields
170+
//! }
171+
//!
172+
//! struct Gadget {
173+
//! id: i32,
174+
//! owner: Rc<Owner>,
175+
//! // ...other fields
176+
//! }
177+
//!
178+
//! fn main() {
179+
//! // Create a reference-counted `Owner`. Note that we've put the `Owner`'s
180+
//! // vector of `Gadget`s inside a `RefCell` so that we can mutate it through
181+
//! // a shared reference.
182+
//! let gadget_owner: Rc<Owner> = Rc::new(
183+
//! Owner {
184+
//! name: "Gadget Man".to_string(),
185+
//! gadgets: RefCell::new(vec![]),
186+
//! }
187+
//! );
188+
//!
189+
//! // Create `Gadget`s belonging to `gadget_owner`, as before.
190+
//! let gadget1 = Rc::new(
191+
//! Gadget {
192+
//! id: 1,
193+
//! owner: Rc::clone(&gadget_owner),
194+
//! }
195+
//! );
196+
//! let gadget2 = Rc::new(
197+
//! Gadget {
198+
//! id: 2,
199+
//! owner: Rc::clone(&gadget_owner),
200+
//! }
201+
//! );
202+
//!
203+
//! // Add the `Gadget`s to their `Owner`.
204+
//! {
205+
//! let mut gadgets = gadget_owner.gadgets.borrow_mut();
206+
//! gadgets.push(Rc::downgrade(&gadget1));
207+
//! gadgets.push(Rc::downgrade(&gadget2));
208+
//!
209+
//! // `RefCell` dynamic borrow ends here.
210+
//! }
211+
//!
212+
//! // Iterate over our `Gadget`s, printing their details out.
213+
//! for gadget_weak in gadget_owner.gadgets.borrow().iter() {
214+
//!
215+
//! // `gadget_weak` is a `Weak<Gadget>`. Since `Weak` pointers can't
216+
//! // guarantee the allocation still exists, we need to call
217+
//! // `upgrade`, which returns an `Option<Rc<Gadget>>`.
218+
//! //
219+
//! // In this case we know the allocation still exists, so we simply
220+
//! // `unwrap` the `Option`. In a more complicated program, you might
221+
//! // need graceful error handling for a `None` result.
222+
//!
223+
//! let gadget = gadget_weak.upgrade().unwrap();
224+
//! println!("Gadget {} owned by {}", gadget.id, gadget.owner.name);
225+
//! }
226+
//!
227+
//! // At the end of the function, `gadget_owner`, `gadget1`, and `gadget2`
228+
//! // are destroyed. There are now no strong (`Rc`) pointers to the
229+
//! // gadgets, so they are destroyed. This zeroes the reference count on
230+
//! // Gadget Man, so he gets destroyed as well.
231+
//! }
232+
//! ```
233+
//!
234+
//! [clone]: Clone::clone
235+
//! [`Cell`]: core::cell::Cell
236+
//! [`RefCell`]: core::cell::RefCell
237+
//! [send]: core::marker::Send
238+
//! [arc]: crate::sync::Arc
239+
//! [`Deref`]: core::ops::Deref
240+
//! [downgrade]: Rc::downgrade
241+
//! [upgrade]: Weak::upgrade
242+
//! [mutability]: core::cell#introducing-mutability-inside-of-something-immutable
243+
//! [fully qualified syntax]: https://doc.rust-lang.org/book/ch19-03-advanced-traits.html#fully-qualified-syntax-for-disambiguation-calling-methods-with-the-same-name
244+
245+
mod rc;
246+
mod utils;
247+
mod weak;
248+
249+
#[cfg(test)]
250+
mod tests;
251+
252+
#[stable(feature = "rust1", since = "1.0.0")]
253+
pub use rc::Rc;
254+
#[stable(feature = "rust1", since = "1.0.0")]
255+
pub use weak::Weak;
256+
257+
pub(crate) use utils::{is_dangling, MarkerEq};

0 commit comments

Comments
 (0)