]> git.lizzy.rs Git - rust.git/blob - src/libstd/rc.rs
auto merge of #10977 : brson/rust/androidtest, r=brson
[rust.git] / src / libstd / rc.rs
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.
4 //
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.
10
11 /*! Task-local reference counted boxes
12
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.
16
17 */
18
19 use ptr::RawPtr;
20 use unstable::intrinsics::transmute;
21 use ops::Drop;
22 use kinds::{Freeze, Send};
23 use clone::{Clone, DeepClone};
24 use cell::RefCell;
25 use cmp::{Eq, TotalEq, Ord, TotalOrd, Ordering};
26
27 struct RcBox<T> {
28     value: T,
29     count: uint
30 }
31
32 /// Immutable reference counted pointer type
33 #[unsafe_no_drop_flag]
34 #[no_send]
35 pub struct Rc<T> {
36     priv ptr: *mut RcBox<T>
37 }
38
39 impl<T: Freeze> Rc<T> {
40     /// Construct a new reference-counted box from a `Freeze` value
41     #[inline]
42     pub fn new(value: T) -> Rc<T> {
43         unsafe {
44             Rc::new_unchecked(value)
45         }
46     }
47 }
48
49 impl<T: Send> Rc<T> {
50     /// Construct a new reference-counted box from a `Send` value
51     #[inline]
52     pub fn from_send(value: T) -> Rc<T> {
53         unsafe {
54             Rc::new_unchecked(value)
55         }
56     }
57 }
58
59 impl<T: Freeze> Rc<RefCell<T>> {
60     /// Construct a new reference-counted box from a `RefCell`-wrapped `Freeze` value
61     #[inline]
62     pub fn from_mut(value: RefCell<T>) -> Rc<RefCell<T>> {
63         unsafe {
64             Rc::new_unchecked(value)
65         }
66     }
67 }
68
69 impl<T> Rc<T> {
70     /// Unsafety construct a new reference-counted box from any value.
71     ///
72     /// It is possible to create cycles, which will leak, and may interact
73     /// poorly with managed pointers.
74     #[inline]
75     pub unsafe fn new_unchecked(value: T) -> Rc<T> {
76         Rc{ptr: transmute(~RcBox{value: value, count: 1})}
77     }
78
79     /// Borrow the value contained in the reference-counted box
80     #[inline]
81     pub fn borrow<'r>(&'r self) -> &'r T {
82         unsafe { &(*self.ptr).value }
83     }
84
85     /// Determine if two reference-counted pointers point to the same object
86     #[inline]
87     pub fn ptr_eq(&self, other: &Rc<T>) -> bool {
88         self.ptr == other.ptr
89     }
90 }
91
92 impl<T: Eq> Eq for Rc<T> {
93     #[inline]
94     fn eq(&self, other: &Rc<T>) -> bool {
95         unsafe { (*self.ptr).value == (*other.ptr).value }
96     }
97
98     #[inline]
99     fn ne(&self, other: &Rc<T>) -> bool {
100         unsafe { (*self.ptr).value != (*other.ptr).value }
101     }
102 }
103
104 impl<T: TotalEq> TotalEq for Rc<T> {
105     #[inline]
106     fn equals(&self, other: &Rc<T>) -> bool {
107         unsafe { (*self.ptr).value.equals(&(*other.ptr).value) }
108     }
109 }
110
111 impl<T: Ord> Ord for Rc<T> {
112     #[inline]
113     fn lt(&self, other: &Rc<T>) -> bool {
114         unsafe { (*self.ptr).value < (*other.ptr).value }
115     }
116
117     #[inline]
118     fn le(&self, other: &Rc<T>) -> bool {
119         unsafe { (*self.ptr).value <= (*other.ptr).value }
120     }
121
122     #[inline]
123     fn ge(&self, other: &Rc<T>) -> bool {
124         unsafe { (*self.ptr).value >= (*other.ptr).value }
125     }
126
127     #[inline]
128     fn gt(&self, other: &Rc<T>) -> bool {
129         unsafe { (*self.ptr).value > (*other.ptr).value }
130     }
131 }
132
133 impl<T: TotalOrd> TotalOrd for Rc<T> {
134     #[inline]
135     fn cmp(&self, other: &Rc<T>) -> Ordering {
136         unsafe { (*self.ptr).value.cmp(&(*other.ptr).value) }
137     }
138 }
139
140 impl<T> Clone for Rc<T> {
141     #[inline]
142     fn clone(&self) -> Rc<T> {
143         unsafe {
144             (*self.ptr).count += 1;
145             Rc{ptr: self.ptr}
146         }
147     }
148 }
149
150 impl<T: DeepClone> DeepClone for Rc<T> {
151     #[inline]
152     fn deep_clone(&self) -> Rc<T> {
153         unsafe { Rc::new_unchecked(self.borrow().deep_clone()) }
154     }
155 }
156
157 #[unsafe_destructor]
158 impl<T> Drop for Rc<T> {
159     fn drop(&mut self) {
160         unsafe {
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);
165                 }
166             }
167         }
168     }
169 }
170
171 #[cfg(test)]
172 mod test_rc {
173     use super::*;
174     use cell::RefCell;
175
176     #[test]
177     fn test_clone() {
178         let x = Rc::from_send(RefCell::new(5));
179         let y = x.clone();
180         x.borrow().with_mut(|inner| {
181             *inner = 20;
182         });
183         assert_eq!(y.borrow().with(|v| *v), 20);
184     }
185
186     #[test]
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| {
191             *inner = 20;
192         });
193         assert_eq!(y.borrow().with(|v| *v), 5);
194     }
195
196     #[test]
197     fn test_simple() {
198         let x = Rc::new(5);
199         assert_eq!(*x.borrow(), 5);
200     }
201
202     #[test]
203     fn test_simple_clone() {
204         let x = Rc::new(5);
205         let y = x.clone();
206         assert_eq!(*x.borrow(), 5);
207         assert_eq!(*y.borrow(), 5);
208     }
209
210     #[test]
211     fn test_destructor() {
212         let x = Rc::from_send(~5);
213         assert_eq!(**x.borrow(), 5);
214     }
215
216     #[test]
217     fn test_from_mut() {
218         let a = 10;
219         let _x = Rc::from_mut(RefCell::new(&a));
220     }
221 }