@@ -24,18 +24,20 @@ pointers, and then storing the parent pointers as `Weak` pointers.
2424*/
2525
2626use cast:: transmute;
27+ use cell:: Cell ;
2728use clone:: Clone ;
2829use cmp:: { Eq , Ord } ;
2930use kinds:: marker;
3031use ops:: { Deref , Drop } ;
3132use option:: { Option , Some , None } ;
3233use ptr;
34+ use ptr:: RawPtr ;
3335use rt:: global_heap:: exchange_free;
3436
3537struct RcBox < T > {
3638 value : T ,
37- strong : uint ,
38- weak : uint
39+ strong : Cell < uint > ,
40+ weak : Cell < uint >
3941}
4042
4143/// Immutable reference counted pointer type
@@ -56,7 +58,11 @@ impl<T> Rc<T> {
5658 // destructor never frees the allocation while the
5759 // strong destructor is running, even if the weak
5860 // 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+ } ) ,
6066 nosend : marker:: NoSend ,
6167 noshare : marker:: NoShare
6268 }
@@ -67,13 +73,11 @@ impl<T> Rc<T> {
6773impl < T > Rc < T > {
6874 /// Downgrade the reference-counted pointer to a weak reference
6975 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
7781 }
7882 }
7983}
@@ -82,24 +86,24 @@ impl<T> Deref<T> for Rc<T> {
8286 /// Borrow the value contained in the reference-counted box
8387 #[ inline( always) ]
8488 fn deref < ' a > ( & ' a self ) -> & ' a T {
85- unsafe { & ( * self . ptr ) . value }
89+ & self . inner ( ) . value
8690 }
8791}
8892
8993#[ unsafe_destructor]
9094impl < T > Drop for Rc < T > {
9195 fn drop ( & mut self ) {
9296 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 {
96100 ptr:: read ( self . deref ( ) ) ; // destroy the contained object
97101
98102 // remove the implicit "strong weak" pointer now
99103 // that we've destroyed the contents.
100- ( * self . ptr ) . weak -= 1 ;
104+ self . dec_weak ( ) ;
101105
102- if ( * self . ptr ) . weak == 0 {
106+ if self . weak ( ) == 0 {
103107 exchange_free ( self . ptr as * u8 )
104108 }
105109 }
@@ -111,10 +115,8 @@ impl<T> Drop for Rc<T> {
111115impl < T > Clone for Rc < T > {
112116 #[ inline]
113117 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 }
118120 }
119121}
120122
@@ -151,13 +153,11 @@ pub struct Weak<T> {
151153impl < T > Weak < T > {
152154 /// Upgrade a weak reference to a strong reference
153155 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 } )
161161 }
162162 }
163163}
@@ -166,11 +166,11 @@ impl<T> Weak<T> {
166166impl < T > Drop for Weak < T > {
167167 fn drop ( & mut self ) {
168168 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 ( ) ;
171171 // the weak count starts at 1, and will only go to
172172 // zero if all the strong pointers have disappeared.
173- if ( * self . ptr ) . weak == 0 {
173+ if self . weak ( ) == 0 {
174174 exchange_free ( self . ptr as * u8 )
175175 }
176176 }
@@ -181,13 +181,44 @@ impl<T> Drop for Weak<T> {
181181impl < T > Clone for Weak < T > {
182182 #[ inline]
183183 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 }
188186 }
189187}
190188
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+
191222#[ cfg( test) ]
192223mod tests {
193224 use prelude:: * ;
0 commit comments