8
8
// option. This file may not be copied, modified, or distributed
9
9
// except according to those terms.
10
10
11
- # [ allow ( missing_doc ) ] ;
11
+ /** Task-local reference counted boxes
12
12
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.
14
16
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`.
21
20
22
21
*/
23
22
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 } ;
36
28
37
29
struct RcBox < T > {
38
30
value : T ,
@@ -43,50 +35,38 @@ struct RcBox<T> {
43
35
#[ unsafe_no_drop_flag]
44
36
#[ no_send]
45
37
pub 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 >
59
39
}
60
40
61
41
impl < 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
+ }
64
48
}
65
49
}
66
50
67
51
impl < 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.
68
57
#[ 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 } ) }
71
60
}
72
- }
73
61
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 }
85
66
}
86
67
}
87
68
88
69
impl < T > Clone for Rc < T > {
89
- /// Return a shallow copy of the reference counted pointer.
90
70
#[ inline]
91
71
fn clone ( & self ) -> Rc < T > {
92
72
unsafe {
@@ -97,56 +77,75 @@ impl<T> Clone for Rc<T> {
97
77
}
98
78
99
79
impl < T : DeepClone > DeepClone for Rc < T > {
100
- /// Return a deep copy of the reference counted pointer.
101
80
#[ inline]
102
81
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
+ }
104
97
}
105
98
}
106
99
107
100
#[ cfg( test) ]
108
101
mod test_rc {
109
102
use super :: * ;
110
- use std :: cell:: Cell ;
103
+ use cell:: Cell ;
111
104
112
105
#[ test]
113
106
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 ) ;
118
114
}
119
- assert_eq ! ( y. borrow( ) . take( ) , 20 ) ;
120
115
}
121
116
122
117
#[ test]
123
118
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 ) ;
128
126
}
129
- assert_eq ! ( y. borrow( ) . take( ) , 5 ) ;
130
127
}
131
128
132
129
#[ test]
133
130
fn test_simple ( ) {
134
- let x = Rc :: from_freeze ( 5 ) ;
131
+ let x = Rc :: new ( 5 ) ;
135
132
assert_eq ! ( * x. borrow( ) , 5 ) ;
136
133
}
137
134
138
135
#[ test]
139
136
fn test_simple_clone ( ) {
140
- let x = Rc :: from_freeze ( 5 ) ;
137
+ let x = Rc :: new ( 5 ) ;
141
138
let y = x. clone ( ) ;
142
139
assert_eq ! ( * x. borrow( ) , 5 ) ;
143
140
assert_eq ! ( * y. borrow( ) , 5 ) ;
144
141
}
145
142
146
143
#[ test]
147
144
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
+ }
150
149
}
151
150
}
152
151
@@ -171,21 +170,30 @@ pub struct RcMut<T> {
171
170
priv ptr: * mut RcMutBox < T > ,
172
171
}
173
172
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) }
177
178
}
178
179
}
179
180
180
181
impl < T : Send > RcMut < T > {
182
+ /// Construct a new mutable reference-counted box from a `Send` value
183
+ #[ inline]
181
184
pub fn from_send ( value : T ) -> RcMut < T > {
182
- unsafe { RcMut :: new ( value) }
185
+ unsafe { RcMut :: new_unchecked ( value) }
183
186
}
184
187
}
185
188
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 } ) }
189
197
}
190
198
}
191
199
@@ -223,7 +231,7 @@ impl<T> Drop for RcMut<T> {
223
231
if self . ptr . is_not_null ( ) {
224
232
( * self . ptr ) . count -= 1 ;
225
233
if ( * self . ptr ) . count == 0 {
226
- let _: ~T = cast :: transmute ( self . ptr ) ;
234
+ let _: ~RcMutBox < T > = transmute ( self . ptr ) ;
227
235
}
228
236
}
229
237
}
@@ -247,7 +255,7 @@ impl<T: DeepClone> DeepClone for RcMut<T> {
247
255
fn deep_clone ( & self ) -> RcMut < T > {
248
256
do self . with_borrow |x| {
249
257
// FIXME: #6497: should avoid freeze (slow)
250
- unsafe { RcMut :: new ( x. deep_clone ( ) ) }
258
+ unsafe { RcMut :: new_unchecked ( x. deep_clone ( ) ) }
251
259
}
252
260
}
253
261
}
@@ -270,7 +278,7 @@ mod test_rc_mut {
270
278
271
279
#[ test]
272
280
fn test_deep_clone ( ) {
273
- let x = RcMut :: from_freeze ( 5 ) ;
281
+ let x = RcMut :: new ( 5 ) ;
274
282
let y = x. deep_clone ( ) ;
275
283
do x. with_mut_borrow |value| {
276
284
* value = 20 ;
@@ -298,7 +306,7 @@ mod test_rc_mut {
298
306
299
307
#[ test]
300
308
fn modify ( ) {
301
- let x = RcMut :: from_freeze ( 5 ) ;
309
+ let x = RcMut :: new ( 5 ) ;
302
310
let y = x. clone ( ) ;
303
311
304
312
do y. with_mut_borrow |a| {
@@ -320,7 +328,7 @@ mod test_rc_mut {
320
328
321
329
#[ test]
322
330
fn release_mutable ( ) {
323
- let x = RcMut :: from_freeze ( 5 ) ;
331
+ let x = RcMut :: new ( 5 ) ;
324
332
do x. with_mut_borrow |_| { }
325
333
do x. with_borrow |_| { }
326
334
}
@@ -340,7 +348,7 @@ mod test_rc_mut {
340
348
#[ test]
341
349
#[ should_fail]
342
350
fn mutable_dupe ( ) {
343
- let x = RcMut :: from_freeze ( 5 ) ;
351
+ let x = RcMut :: new ( 5 ) ;
344
352
let y = x. clone ( ) ;
345
353
346
354
do x. with_mut_borrow |_| {
@@ -364,7 +372,7 @@ mod test_rc_mut {
364
372
#[ test]
365
373
#[ should_fail]
366
374
fn restore_freeze ( ) {
367
- let x = RcMut :: from_freeze ( 5 ) ;
375
+ let x = RcMut :: new ( 5 ) ;
368
376
let y = x. clone ( ) ;
369
377
370
378
do x. with_borrow |_| {
0 commit comments