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
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.
20 use unstable::intrinsics::transmute;
22 use kinds::{Freeze, Send};
23 use clone::{Clone, DeepClone};
25 use cmp::{Eq, TotalEq, Ord, TotalOrd, Ordering};
32 /// Immutable reference counted pointer type
33 #[unsafe_no_drop_flag]
36 priv ptr: *mut RcBox<T>
39 impl<T: Freeze> Rc<T> {
40 /// Construct a new reference-counted box from a `Freeze` value
42 pub fn new(value: T) -> Rc<T> {
44 Rc::new_unchecked(value)
50 /// Construct a new reference-counted box from a `Send` value
52 pub fn from_send(value: T) -> Rc<T> {
54 Rc::new_unchecked(value)
59 impl<T: Freeze> Rc<RefCell<T>> {
60 /// Construct a new reference-counted box from a `RefCell`-wrapped `Freeze` value
62 pub fn from_mut(value: RefCell<T>) -> Rc<RefCell<T>> {
64 Rc::new_unchecked(value)
70 /// Unsafety construct a new reference-counted box from any value.
72 /// It is possible to create cycles, which will leak, and may interact
73 /// poorly with managed pointers.
75 pub unsafe fn new_unchecked(value: T) -> Rc<T> {
76 Rc{ptr: transmute(~RcBox{value: value, count: 1})}
79 /// Borrow the value contained in the reference-counted box
81 pub fn borrow<'r>(&'r self) -> &'r T {
82 unsafe { &(*self.ptr).value }
85 /// Determine if two reference-counted pointers point to the same object
87 pub fn ptr_eq(&self, other: &Rc<T>) -> bool {
92 impl<T: Eq> Eq for Rc<T> {
94 fn eq(&self, other: &Rc<T>) -> bool {
95 unsafe { (*self.ptr).value == (*other.ptr).value }
99 fn ne(&self, other: &Rc<T>) -> bool {
100 unsafe { (*self.ptr).value != (*other.ptr).value }
104 impl<T: TotalEq> TotalEq for Rc<T> {
106 fn equals(&self, other: &Rc<T>) -> bool {
107 unsafe { (*self.ptr).value.equals(&(*other.ptr).value) }
111 impl<T: Ord> Ord for Rc<T> {
113 fn lt(&self, other: &Rc<T>) -> bool {
114 unsafe { (*self.ptr).value < (*other.ptr).value }
118 fn le(&self, other: &Rc<T>) -> bool {
119 unsafe { (*self.ptr).value <= (*other.ptr).value }
123 fn ge(&self, other: &Rc<T>) -> bool {
124 unsafe { (*self.ptr).value >= (*other.ptr).value }
128 fn gt(&self, other: &Rc<T>) -> bool {
129 unsafe { (*self.ptr).value > (*other.ptr).value }
133 impl<T: TotalOrd> TotalOrd for Rc<T> {
135 fn cmp(&self, other: &Rc<T>) -> Ordering {
136 unsafe { (*self.ptr).value.cmp(&(*other.ptr).value) }
140 impl<T> Clone for Rc<T> {
142 fn clone(&self) -> Rc<T> {
144 (*self.ptr).count += 1;
150 impl<T: DeepClone> DeepClone for Rc<T> {
152 fn deep_clone(&self) -> Rc<T> {
153 unsafe { Rc::new_unchecked(self.borrow().deep_clone()) }
158 impl<T> Drop for Rc<T> {
161 if self.ptr.is_not_null() {
162 (*self.ptr).count -= 1;
163 if (*self.ptr).count == 0 {
164 let _: ~RcBox<T> = transmute(self.ptr);
178 let x = Rc::from_send(RefCell::new(5));
180 x.borrow().with_mut(|inner| {
183 assert_eq!(y.borrow().with(|v| *v), 20);
187 fn test_deep_clone() {
188 let x = Rc::from_send(RefCell::new(5));
189 let y = x.deep_clone();
190 x.borrow().with_mut(|inner| {
193 assert_eq!(y.borrow().with(|v| *v), 5);
199 assert_eq!(*x.borrow(), 5);
203 fn test_simple_clone() {
206 assert_eq!(*x.borrow(), 5);
207 assert_eq!(*y.borrow(), 5);
211 fn test_destructor() {
212 let x = Rc::from_send(~5);
213 assert_eq!(**x.borrow(), 5);
219 let _x = Rc::from_mut(RefCell::new(&a));