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