@@ -24,18 +24,20 @@ pointers, and then storing the parent pointers as `Weak` pointers.
24
24
*/
25
25
26
26
use cast:: transmute;
27
+ use cell:: Cell ;
27
28
use clone:: Clone ;
28
29
use cmp:: { Eq , Ord } ;
29
30
use kinds:: marker;
30
31
use ops:: { Deref , Drop } ;
31
32
use option:: { Option , Some , None } ;
32
33
use ptr;
34
+ use ptr:: RawPtr ;
33
35
use rt:: global_heap:: exchange_free;
34
36
35
37
struct RcBox < T > {
36
38
value : T ,
37
- strong : uint ,
38
- weak : uint
39
+ strong : Cell < uint > ,
40
+ weak : Cell < uint >
39
41
}
40
42
41
43
/// Immutable reference counted pointer type
@@ -56,7 +58,11 @@ impl<T> Rc<T> {
56
58
// destructor never frees the allocation while the
57
59
// strong destructor is running, even if the weak
58
60
// pointer is stored inside the strong one.
59
- ptr : transmute ( ~RcBox { value : value, strong : 1 , weak : 1 } ) ,
61
+ ptr : transmute ( ~RcBox {
62
+ value : value,
63
+ strong : Cell :: new ( 1 ) ,
64
+ weak : Cell :: new ( 1 )
65
+ } ) ,
60
66
nosend : marker:: NoSend ,
61
67
noshare : marker:: NoShare
62
68
}
@@ -67,13 +73,11 @@ impl<T> Rc<T> {
67
73
impl < T > Rc < T > {
68
74
/// Downgrade the reference-counted pointer to a weak reference
69
75
pub fn downgrade ( & self ) -> Weak < T > {
70
- unsafe {
71
- ( * self . ptr ) . weak += 1 ;
72
- Weak {
73
- ptr : self . ptr ,
74
- nosend : marker:: NoSend ,
75
- noshare : marker:: NoShare
76
- }
76
+ self . inc_weak ( ) ;
77
+ Weak {
78
+ ptr : self . ptr ,
79
+ nosend : marker:: NoSend ,
80
+ noshare : marker:: NoShare
77
81
}
78
82
}
79
83
}
@@ -82,24 +86,24 @@ impl<T> Deref<T> for Rc<T> {
82
86
/// Borrow the value contained in the reference-counted box
83
87
#[ inline( always) ]
84
88
fn deref < ' a > ( & ' a self ) -> & ' a T {
85
- unsafe { & ( * self . ptr ) . value }
89
+ & self . inner ( ) . value
86
90
}
87
91
}
88
92
89
93
#[ unsafe_destructor]
90
94
impl < T > Drop for Rc < T > {
91
95
fn drop ( & mut self ) {
92
96
unsafe {
93
- if self . ptr != 0 as * mut RcBox < T > {
94
- ( * self . ptr ) . strong -= 1 ;
95
- if ( * self . ptr ) . strong == 0 {
97
+ if ! self . ptr . is_null ( ) {
98
+ self . dec_strong ( ) ;
99
+ if self . strong ( ) == 0 {
96
100
ptr:: read ( self . deref ( ) ) ; // destroy the contained object
97
101
98
102
// remove the implicit "strong weak" pointer now
99
103
// that we've destroyed the contents.
100
- ( * self . ptr ) . weak -= 1 ;
104
+ self . dec_weak ( ) ;
101
105
102
- if ( * self . ptr ) . weak == 0 {
106
+ if self . weak ( ) == 0 {
103
107
exchange_free ( self . ptr as * u8 )
104
108
}
105
109
}
@@ -111,10 +115,8 @@ impl<T> Drop for Rc<T> {
111
115
impl < T > Clone for Rc < T > {
112
116
#[ inline]
113
117
fn clone ( & self ) -> Rc < T > {
114
- unsafe {
115
- ( * self . ptr ) . strong += 1 ;
116
- Rc { ptr : self . ptr , nosend : marker:: NoSend , noshare : marker:: NoShare }
117
- }
118
+ self . inc_strong ( ) ;
119
+ Rc { ptr : self . ptr , nosend : marker:: NoSend , noshare : marker:: NoShare }
118
120
}
119
121
}
120
122
@@ -151,13 +153,11 @@ pub struct Weak<T> {
151
153
impl < T > Weak < T > {
152
154
/// Upgrade a weak reference to a strong reference
153
155
pub fn upgrade ( & self ) -> Option < Rc < T > > {
154
- unsafe {
155
- if ( * self . ptr ) . strong == 0 {
156
- None
157
- } else {
158
- ( * self . ptr ) . strong += 1 ;
159
- Some ( Rc { ptr : self . ptr , nosend : marker:: NoSend , noshare : marker:: NoShare } )
160
- }
156
+ if self . strong ( ) == 0 {
157
+ None
158
+ } else {
159
+ self . inc_strong ( ) ;
160
+ Some ( Rc { ptr : self . ptr , nosend : marker:: NoSend , noshare : marker:: NoShare } )
161
161
}
162
162
}
163
163
}
@@ -166,11 +166,11 @@ impl<T> Weak<T> {
166
166
impl < T > Drop for Weak < T > {
167
167
fn drop ( & mut self ) {
168
168
unsafe {
169
- if self . ptr != 0 as * mut RcBox < T > {
170
- ( * self . ptr ) . weak -= 1 ;
169
+ if ! self . ptr . is_null ( ) {
170
+ self . dec_weak ( ) ;
171
171
// the weak count starts at 1, and will only go to
172
172
// zero if all the strong pointers have disappeared.
173
- if ( * self . ptr ) . weak == 0 {
173
+ if self . weak ( ) == 0 {
174
174
exchange_free ( self . ptr as * u8 )
175
175
}
176
176
}
@@ -181,13 +181,44 @@ impl<T> Drop for Weak<T> {
181
181
impl < T > Clone for Weak < T > {
182
182
#[ inline]
183
183
fn clone ( & self ) -> Weak < T > {
184
- unsafe {
185
- ( * self . ptr ) . weak += 1 ;
186
- Weak { ptr : self . ptr , nosend : marker:: NoSend , noshare : marker:: NoShare }
187
- }
184
+ self . inc_weak ( ) ;
185
+ Weak { ptr : self . ptr , nosend : marker:: NoSend , noshare : marker:: NoShare }
188
186
}
189
187
}
190
188
189
+ #[ allow( missing_doc) ]
190
+ trait RcBoxPtr < T > {
191
+ fn inner < ' a > ( & ' a self ) -> & ' a RcBox < T > ;
192
+
193
+ #[ inline]
194
+ fn strong ( & self ) -> uint { self . inner ( ) . strong . get ( ) }
195
+
196
+ #[ inline]
197
+ fn inc_strong ( & self ) { self . inner ( ) . strong . set ( self . strong ( ) + 1 ) ; }
198
+
199
+ #[ inline]
200
+ fn dec_strong ( & self ) { self . inner ( ) . strong . set ( self . strong ( ) - 1 ) ; }
201
+
202
+ #[ inline]
203
+ fn weak ( & self ) -> uint { self . inner ( ) . weak . get ( ) }
204
+
205
+ #[ inline]
206
+ fn inc_weak ( & self ) { self . inner ( ) . weak . set ( self . weak ( ) + 1 ) ; }
207
+
208
+ #[ inline]
209
+ fn dec_weak ( & self ) { self . inner ( ) . weak . set ( self . weak ( ) - 1 ) ; }
210
+ }
211
+
212
+ impl < T > RcBoxPtr < T > for Rc < T > {
213
+ #[ inline( always) ]
214
+ fn inner < ' a > ( & ' a self ) -> & ' a RcBox < T > { unsafe { & ( * self . ptr ) } }
215
+ }
216
+
217
+ impl < T > RcBoxPtr < T > for Weak < T > {
218
+ #[ inline( always) ]
219
+ fn inner < ' a > ( & ' a self ) -> & ' a RcBox < T > { unsafe { & ( * self . ptr ) } }
220
+ }
221
+
191
222
#[ cfg( test) ]
192
223
mod tests {
193
224
use prelude:: * ;
0 commit comments