88// option. This file may not be copied, modified, or distributed
99// except according to those terms.
1010
11- # [ allow ( missing_doc ) ] ;
11+ /** Task-local reference counted boxes
1212
13- /** Task-local reference counted smart pointers
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.
1416
15- Task-local reference counted smart pointers are an alternative to managed boxes with deterministic
16- destruction. They are restricted to containing types that are either `Send` or `Freeze` (or both) to
17- prevent cycles.
18-
19- Neither `Rc<T>` or `RcMut<T>` is ever `Send` and `RcMut<T>` is never `Freeze`. If `T` is `Freeze`, a
20- cycle cannot be created with `Rc<T>` because there is no way to modify it after creation.
17+ The `RcMut` type provides shared ownership of a mutable value. Since multiple owners prevent
18+ inherited mutability, a dynamic freezing check is used to maintain the invariant that an `&mut`
19+ reference is a unique handle and the type is marked as non-`Freeze`.
2120
2221*/
2322
24-
25- use std:: cast;
26- use std:: ptr;
27- use std:: unstable:: intrinsics;
28-
29- // Convert ~T into *mut T without dropping it
30- #[ inline]
31- unsafe fn owned_to_raw < T > ( mut box : ~T ) -> * mut T {
32- let ptr = ptr:: to_mut_unsafe_ptr ( box) ;
33- intrinsics:: forget ( box) ;
34- ptr
35- }
23+ use ptr:: RawPtr ;
24+ use unstable:: intrinsics:: transmute;
25+ use ops:: Drop ;
26+ use kinds:: { Freeze , Send } ;
27+ use clone:: { Clone , DeepClone } ;
3628
3729struct RcBox < T > {
3830 value : T ,
@@ -43,50 +35,38 @@ struct RcBox<T> {
4335#[ unsafe_no_drop_flag]
4436#[ no_send]
4537pub struct Rc < T > {
46- priv ptr: * mut RcBox < T > ,
47- }
48-
49- impl < T > Rc < T > {
50- unsafe fn new ( value : T ) -> Rc < T > {
51- Rc { ptr : owned_to_raw ( ~RcBox { value : value, count : 1 } ) }
52- }
53- }
54-
55- impl < T : Send > Rc < T > {
56- pub fn from_send ( value : T ) -> Rc < T > {
57- unsafe { Rc :: new ( value) }
58- }
38+ priv ptr: * mut RcBox < T >
5939}
6040
6141impl < T : Freeze > Rc < T > {
62- pub fn from_freeze ( value : T ) -> Rc < T > {
63- unsafe { Rc :: new ( value) }
42+ /// Construct a new reference-counted box from a `Freeze` value
43+ #[ inline]
44+ pub fn new ( value : T ) -> Rc < T > {
45+ unsafe {
46+ Rc :: new_unchecked ( value)
47+ }
6448 }
6549}
6650
6751impl < T > Rc < T > {
52+ /// Unsafety construct a new reference-counted box from any value.
53+ ///
54+ /// If the type is not `Freeze`, the `Rc` box will incorrectly still be considered as a `Freeze`
55+ /// type. It is also possible to create cycles, which will leak, and may interact poorly with
56+ /// managed pointers.
6857 #[ inline]
69- pub fn borrow < ' r > ( & ' r self ) -> & ' r T {
70- unsafe { cast :: copy_lifetime ( self , & ( * self . ptr ) . value ) }
58+ pub unsafe fn new_unchecked ( value : T ) -> Rc < T > {
59+ Rc { ptr : transmute ( ~ RcBox { value : value , count : 1 } ) }
7160 }
72- }
7361
74- #[ unsafe_destructor]
75- impl < T > Drop for Rc < T > {
76- fn drop ( & mut self ) {
77- unsafe {
78- if self . ptr . is_not_null ( ) {
79- ( * self . ptr ) . count -= 1 ;
80- if ( * self . ptr ) . count == 0 {
81- let _: ~T = cast:: transmute ( self . ptr ) ;
82- }
83- }
84- }
62+ /// Borrow the value contained in the reference-counted box
63+ #[ inline]
64+ pub fn borrow < ' r > ( & ' r self ) -> & ' r T {
65+ unsafe { & ( * self . ptr ) . value }
8566 }
8667}
8768
8869impl < T > Clone for Rc < T > {
89- /// Return a shallow copy of the reference counted pointer.
9070 #[ inline]
9171 fn clone ( & self ) -> Rc < T > {
9272 unsafe {
@@ -97,56 +77,75 @@ impl<T> Clone for Rc<T> {
9777}
9878
9979impl < T : DeepClone > DeepClone for Rc < T > {
100- /// Return a deep copy of the reference counted pointer.
10180 #[ inline]
10281 fn deep_clone ( & self ) -> Rc < T > {
103- unsafe { Rc :: new ( self . borrow ( ) . deep_clone ( ) ) }
82+ unsafe { Rc :: new_unchecked ( self . borrow ( ) . deep_clone ( ) ) }
83+ }
84+ }
85+
86+ #[ unsafe_destructor]
87+ impl < T > Drop for Rc < T > {
88+ fn drop ( & mut self ) {
89+ unsafe {
90+ if self . ptr . is_not_null ( ) {
91+ ( * self . ptr ) . count -= 1 ;
92+ if ( * self . ptr ) . count == 0 {
93+ let _: ~RcBox < T > = transmute ( self . ptr ) ;
94+ }
95+ }
96+ }
10497 }
10598}
10699
107100#[ cfg( test) ]
108101mod test_rc {
109102 use super :: * ;
110- use std :: cell:: Cell ;
103+ use cell:: Cell ;
111104
112105 #[ test]
113106 fn test_clone( ) {
114- let x = Rc :: from_send ( Cell :: new ( 5 ) ) ;
115- let y = x. clone ( ) ;
116- do x. borrow ( ) . with_mut_ref |inner| {
117- * inner = 20 ;
107+ unsafe {
108+ let x = Rc :: new_unchecked ( Cell :: new ( 5 ) ) ;
109+ let y = x. clone ( ) ;
110+ do x. borrow ( ) . with_mut_ref |inner| {
111+ * inner = 20 ;
112+ }
113+ assert_eq ! ( y. borrow( ) . take( ) , 20 ) ;
118114 }
119- assert_eq ! ( y. borrow( ) . take( ) , 20 ) ;
120115 }
121116
122117 #[ test]
123118 fn test_deep_clone ( ) {
124- let x = Rc :: from_send ( Cell :: new ( 5 ) ) ;
125- let y = x. deep_clone ( ) ;
126- do x. borrow ( ) . with_mut_ref |inner| {
127- * inner = 20 ;
119+ unsafe {
120+ let x = Rc :: new_unchecked ( Cell :: new ( 5 ) ) ;
121+ let y = x. deep_clone ( ) ;
122+ do x. borrow ( ) . with_mut_ref |inner| {
123+ * inner = 20 ;
124+ }
125+ assert_eq ! ( y. borrow( ) . take( ) , 5 ) ;
128126 }
129- assert_eq ! ( y. borrow( ) . take( ) , 5 ) ;
130127 }
131128
132129 #[ test]
133130 fn test_simple ( ) {
134- let x = Rc :: from_freeze ( 5 ) ;
131+ let x = Rc :: new ( 5 ) ;
135132 assert_eq ! ( * x. borrow( ) , 5 ) ;
136133 }
137134
138135 #[ test]
139136 fn test_simple_clone ( ) {
140- let x = Rc :: from_freeze ( 5 ) ;
137+ let x = Rc :: new ( 5 ) ;
141138 let y = x. clone ( ) ;
142139 assert_eq ! ( * x. borrow( ) , 5 ) ;
143140 assert_eq ! ( * y. borrow( ) , 5 ) ;
144141 }
145142
146143 #[ test]
147144 fn test_destructor ( ) {
148- let x = Rc :: from_send ( ~5 ) ;
149- assert_eq ! ( * * x. borrow( ) , 5 ) ;
145+ unsafe {
146+ let x = Rc :: new_unchecked ( ~5 ) ;
147+ assert_eq ! ( * * x. borrow( ) , 5 ) ;
148+ }
150149 }
151150}
152151
@@ -171,21 +170,30 @@ pub struct RcMut<T> {
171170 priv ptr: * mut RcMutBox < T > ,
172171}
173172
174- impl < T > RcMut < T > {
175- unsafe fn new ( value : T ) -> RcMut < T > {
176- RcMut { ptr : owned_to_raw ( ~RcMutBox { value : value, count : 1 , borrow : Nothing } ) }
173+ impl < T : Freeze > RcMut < T > {
174+ /// Construct a new mutable reference-counted box from a `Freeze` value
175+ #[ inline]
176+ pub fn new ( value : T ) -> RcMut < T > {
177+ unsafe { RcMut :: new_unchecked ( value) }
177178 }
178179}
179180
180181impl < T : Send > RcMut < T > {
182+ /// Construct a new mutable reference-counted box from a `Send` value
183+ #[ inline]
181184 pub fn from_send ( value : T ) -> RcMut < T > {
182- unsafe { RcMut :: new ( value) }
185+ unsafe { RcMut :: new_unchecked ( value) }
183186 }
184187}
185188
186- impl < T : Freeze > RcMut < T > {
187- pub fn from_freeze ( value : T ) -> RcMut < T > {
188- unsafe { RcMut :: new ( value) }
189+ impl < T > RcMut < T > {
190+ /// Unsafety construct a new mutable reference-counted box from any value.
191+ ///
192+ /// It is possible to create cycles, which will leak, and may interact
193+ /// poorly with managed pointers.
194+ #[ inline]
195+ pub unsafe fn new_unchecked ( value : T ) -> RcMut < T > {
196+ RcMut { ptr : transmute ( ~RcMutBox { value : value, count : 1 , borrow : Nothing } ) }
189197 }
190198}
191199
@@ -223,7 +231,7 @@ impl<T> Drop for RcMut<T> {
223231 if self . ptr . is_not_null ( ) {
224232 ( * self . ptr ) . count -= 1 ;
225233 if ( * self . ptr ) . count == 0 {
226- let _: ~T = cast :: transmute ( self . ptr ) ;
234+ let _: ~RcMutBox < T > = transmute ( self . ptr ) ;
227235 }
228236 }
229237 }
@@ -247,7 +255,7 @@ impl<T: DeepClone> DeepClone for RcMut<T> {
247255 fn deep_clone ( & self ) -> RcMut < T > {
248256 do self . with_borrow |x| {
249257 // FIXME: #6497: should avoid freeze (slow)
250- unsafe { RcMut :: new ( x. deep_clone ( ) ) }
258+ unsafe { RcMut :: new_unchecked ( x. deep_clone ( ) ) }
251259 }
252260 }
253261}
@@ -270,7 +278,7 @@ mod test_rc_mut {
270278
271279 #[ test]
272280 fn test_deep_clone ( ) {
273- let x = RcMut :: from_freeze ( 5 ) ;
281+ let x = RcMut :: new ( 5 ) ;
274282 let y = x. deep_clone ( ) ;
275283 do x. with_mut_borrow |value| {
276284 * value = 20 ;
@@ -298,7 +306,7 @@ mod test_rc_mut {
298306
299307 #[ test]
300308 fn modify ( ) {
301- let x = RcMut :: from_freeze ( 5 ) ;
309+ let x = RcMut :: new ( 5 ) ;
302310 let y = x. clone ( ) ;
303311
304312 do y. with_mut_borrow |a| {
@@ -320,7 +328,7 @@ mod test_rc_mut {
320328
321329 #[ test]
322330 fn release_mutable ( ) {
323- let x = RcMut :: from_freeze ( 5 ) ;
331+ let x = RcMut :: new ( 5 ) ;
324332 do x. with_mut_borrow |_| { }
325333 do x. with_borrow |_| { }
326334 }
@@ -340,7 +348,7 @@ mod test_rc_mut {
340348 #[ test]
341349 #[ should_fail]
342350 fn mutable_dupe ( ) {
343- let x = RcMut :: from_freeze ( 5 ) ;
351+ let x = RcMut :: new ( 5 ) ;
344352 let y = x. clone ( ) ;
345353
346354 do x. with_mut_borrow |_| {
@@ -364,7 +372,7 @@ mod test_rc_mut {
364372 #[ test]
365373 #[ should_fail]
366374 fn restore_freeze ( ) {
367- let x = RcMut :: from_freeze ( 5 ) ;
375+ let x = RcMut :: new ( 5 ) ;
368376 let y = x. clone ( ) ;
369377
370378 do x. with_borrow |_| {
0 commit comments