1 // Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 /*! Task-local reference-counted boxes (`Rc` type)
13 The `Rc` type provides shared ownership of an immutable value. Destruction is deterministic, and
14 will occur as soon as the last owner is gone. It is marked as non-sendable because it avoids the
15 overhead of atomic reference counting.
17 The `downgrade` method can be used to create a non-owning `Weak` pointer to the box. A `Weak`
18 pointer can be upgraded to an `Rc` pointer, but will return `None` if the value has already been
21 For example, a tree with parent pointers can be represented by putting the nodes behind `Strong`
22 pointers, and then storing the parent pointers as `Weak` pointers.
29 use cmp::{Eq, Ord, TotalEq, TotalOrd, Ordering};
31 use ops::{Deref, Drop};
32 use option::{Option, Some, None};
35 use rt::global_heap::exchange_free;
43 /// Immutable reference counted pointer type
44 #[unsafe_no_drop_flag]
46 priv ptr: *mut RcBox<T>,
47 priv nosend: marker::NoSend,
48 priv noshare: marker::NoShare
52 /// Construct a new reference-counted box
53 pub fn new(value: T) -> Rc<T> {
56 // there is an implicit weak pointer owned by all the
57 // strong pointers, which ensures that the weak
58 // destructor never frees the allocation while the
59 // strong destructor is running, even if the weak
60 // pointer is stored inside the strong one.
61 ptr: transmute(~RcBox {
66 nosend: marker::NoSend,
67 noshare: marker::NoShare
74 /// Downgrade the reference-counted pointer to a weak reference
75 pub fn downgrade(&self) -> Weak<T> {
79 nosend: marker::NoSend,
80 noshare: marker::NoShare
85 impl<T> Deref<T> for Rc<T> {
86 /// Borrow the value contained in the reference-counted box
88 fn deref<'a>(&'a self) -> &'a T {
94 impl<T> Drop for Rc<T> {
97 if !self.ptr.is_null() {
99 if self.strong() == 0 {
100 ptr::read(self.deref()); // destroy the contained object
102 // remove the implicit "strong weak" pointer now
103 // that we've destroyed the contents.
106 if self.weak() == 0 {
107 exchange_free(self.ptr as *u8)
115 impl<T> Clone for Rc<T> {
117 fn clone(&self) -> Rc<T> {
119 Rc { ptr: self.ptr, nosend: marker::NoSend, noshare: marker::NoShare }
123 impl<T: Eq> Eq for Rc<T> {
125 fn eq(&self, other: &Rc<T>) -> bool { **self == **other }
127 fn ne(&self, other: &Rc<T>) -> bool { **self != **other }
130 impl<T: TotalEq> TotalEq for Rc<T> {}
132 impl<T: Ord> Ord for Rc<T> {
134 fn lt(&self, other: &Rc<T>) -> bool { **self < **other }
137 fn le(&self, other: &Rc<T>) -> bool { **self <= **other }
140 fn gt(&self, other: &Rc<T>) -> bool { **self > **other }
143 fn ge(&self, other: &Rc<T>) -> bool { **self >= **other }
146 impl<T: TotalOrd> TotalOrd for Rc<T> {
148 fn cmp(&self, other: &Rc<T>) -> Ordering { (**self).cmp(&**other) }
151 /// Weak reference to a reference-counted box
152 #[unsafe_no_drop_flag]
154 priv ptr: *mut RcBox<T>,
155 priv nosend: marker::NoSend,
156 priv noshare: marker::NoShare
160 /// Upgrade a weak reference to a strong reference
161 pub fn upgrade(&self) -> Option<Rc<T>> {
162 if self.strong() == 0 {
166 Some(Rc { ptr: self.ptr, nosend: marker::NoSend, noshare: marker::NoShare })
172 impl<T> Drop for Weak<T> {
175 if !self.ptr.is_null() {
177 // the weak count starts at 1, and will only go to
178 // zero if all the strong pointers have disappeared.
179 if self.weak() == 0 {
180 exchange_free(self.ptr as *u8)
187 impl<T> Clone for Weak<T> {
189 fn clone(&self) -> Weak<T> {
191 Weak { ptr: self.ptr, nosend: marker::NoSend, noshare: marker::NoShare }
195 #[allow(missing_doc)]
197 fn inner<'a>(&'a self) -> &'a RcBox<T>;
200 fn strong(&self) -> uint { self.inner().strong.get() }
203 fn inc_strong(&self) { self.inner().strong.set(self.strong() + 1); }
206 fn dec_strong(&self) { self.inner().strong.set(self.strong() - 1); }
209 fn weak(&self) -> uint { self.inner().weak.get() }
212 fn inc_weak(&self) { self.inner().weak.set(self.weak() + 1); }
215 fn dec_weak(&self) { self.inner().weak.set(self.weak() - 1); }
218 impl<T> RcBoxPtr<T> for Rc<T> {
220 fn inner<'a>(&'a self) -> &'a RcBox<T> { unsafe { &(*self.ptr) } }
223 impl<T> RcBoxPtr<T> for Weak<T> {
225 fn inner<'a>(&'a self) -> &'a RcBox<T> { unsafe { &(*self.ptr) } }
236 let x = Rc::new(RefCell::new(5));
238 *x.borrow_mut() = 20;
239 assert_eq!(*y.borrow(), 20);
249 fn test_simple_clone() {
257 fn test_destructor() {
265 let y = x.downgrade();
266 assert!(y.upgrade().is_some());
272 let y = x.downgrade();
274 assert!(y.upgrade().is_none());
281 let a = Rc::new(RefCell::new(Gc::new(1)));
282 assert!(a.try_borrow_mut().is_some());
286 fn weak_self_cyclic() {
288 x: RefCell<Option<Weak<Cycle>>>
291 let a = Rc::new(Cycle { x: RefCell::new(None) });
292 let b = a.clone().downgrade();
293 *a.x.borrow_mut() = Some(b);
295 // hopefully we don't double-free (or leak)...