@@ -14,19 +14,27 @@ The `Rc` type provides shared ownership of an immutable value. Destruction is de
1414will occur as soon as the last owner is gone. It is marked as non-sendable because it avoids the
1515overhead of atomic reference counting.
1616
17+ The `downgrade` method can be used to create a non-owning `Weak` pointer to the box. A `Weak`
18+ pointer can be upgraded to an `Rc` pointer, but will return `None` if the value has already been
19+ freed.
20+
21+ For example, a tree with parent pointers can be represented by putting the nodes behind `Strong`
22+ pointers, and then storing the parent pointers as `Weak` pointers.
23+
1724*/
1825
19- use ptr:: RawPtr ;
20- use unstable:: intrinsics:: transmute;
26+ use cast:: transmute;
2127use ops:: Drop ;
22- use kinds :: { Freeze , Send } ;
28+ use cmp :: { Eq , Ord } ;
2329use clone:: { Clone , DeepClone } ;
24- use cell:: RefCell ;
25- use cmp:: { Eq , TotalEq , Ord , TotalOrd , Ordering } ;
30+ use rt:: global_heap:: exchange_free;
31+ use ptr:: read_ptr;
32+ use option:: { Option , Some , None } ;
2633
2734struct RcBox < T > {
2835 value : T ,
29- count : uint
36+ strong : uint ,
37+ weak : uint
3038}
3139
3240/// Immutable reference counted pointer type
@@ -36,147 +44,141 @@ pub struct Rc<T> {
3644 priv ptr: * mut RcBox < T >
3745}
3846
39- impl < T : Freeze > Rc < T > {
40- /// Construct a new reference-counted box from a `Freeze` value
41- #[ inline]
47+ impl < T > Rc < T > {
48+ /// Construct a new reference-counted box
4249 pub fn new ( value : T ) -> Rc < T > {
4350 unsafe {
44- Rc :: new_unchecked ( value)
51+ Rc { ptr : transmute ( ~ RcBox { value : value , strong : 1 , weak : 0 } ) }
4552 }
4653 }
4754}
4855
49- impl < T : Send > Rc < T > {
50- /// Construct a new reference-counted box from a `Send` value
51- #[ inline]
52- pub fn from_send ( value : T ) -> Rc < T > {
56+ impl < T > Rc < T > {
57+ /// Borrow the value contained in the reference-counted box
58+ #[ inline( always) ]
59+ pub fn borrow < ' a > ( & ' a self ) -> & ' a T {
60+ unsafe { & ( * self . ptr ) . value }
61+ }
62+
63+ /// Downgrade the reference-counted pointer to a weak reference
64+ pub fn downgrade ( & self ) -> Weak < T > {
5365 unsafe {
54- Rc :: new_unchecked ( value)
66+ ( * self . ptr ) . weak += 1 ;
67+ Weak { ptr : self . ptr }
5568 }
5669 }
5770}
5871
59- impl < T : Freeze > Rc < RefCell < T > > {
60- /// Construct a new reference-counted box from a `RefCell`-wrapped `Freeze` value
61- #[ inline]
62- pub fn from_mut ( value : RefCell < T > ) -> Rc < RefCell < T > > {
72+ #[ unsafe_destructor]
73+ impl < T > Drop for Rc < T > {
74+ fn drop ( & mut self ) {
6375 unsafe {
64- Rc :: new_unchecked ( value)
76+ if self . ptr != 0 as * mut RcBox < T > {
77+ ( * self . ptr ) . strong -= 1 ;
78+ if ( * self . ptr ) . strong == 0 {
79+ read_ptr ( self . borrow ( ) ) ; // destroy the contained object
80+ if ( * self . ptr ) . weak == 0 {
81+ exchange_free ( self . ptr as * mut u8 as * i8 )
82+ }
83+ }
84+ }
6585 }
6686 }
6787}
6888
69- impl < T > Rc < T > {
70- /// Unsafety construct a new reference-counted box from any value.
71- ///
72- /// It is possible to create cycles, which will leak, and may interact
73- /// poorly with managed pointers.
74- #[ inline]
75- pub unsafe fn new_unchecked ( value : T ) -> Rc < T > {
76- Rc { ptr : transmute ( ~RcBox { value : value, count : 1 } ) }
77- }
78-
79- /// Borrow the value contained in the reference-counted box
89+ impl < T > Clone for Rc < T > {
8090 #[ inline]
81- pub fn borrow < ' r > ( & ' r self ) -> & ' r T {
82- unsafe { & ( * self . ptr ) . value }
91+ fn clone ( & self ) -> Rc < T > {
92+ unsafe {
93+ ( * self . ptr ) . strong += 1 ;
94+ Rc { ptr : self . ptr }
95+ }
8396 }
97+ }
8498
85- /// Determine if two reference-counted pointers point to the same object
99+ impl < T : DeepClone > DeepClone for Rc < T > {
86100 #[ inline]
87- pub fn ptr_eq ( & self , other : & Rc < T > ) -> bool {
88- self . ptr == other . ptr
101+ fn deep_clone ( & self ) -> Rc < T > {
102+ Rc :: new ( self . borrow ( ) . deep_clone ( ) )
89103 }
90104}
91105
92106impl < T : Eq > Eq for Rc < T > {
93- #[ inline]
94- fn eq ( & self , other : & Rc < T > ) -> bool {
95- unsafe { ( * self . ptr ) . value == ( * other. ptr ) . value }
96- }
107+ #[ inline( always) ]
108+ fn eq ( & self , other : & Rc < T > ) -> bool { * self . borrow ( ) == * other. borrow ( ) }
97109
98- #[ inline]
99- fn ne ( & self , other : & Rc < T > ) -> bool {
100- unsafe { ( * self . ptr ) . value != ( * other. ptr ) . value }
101- }
102- }
103-
104- impl < T : TotalEq > TotalEq for Rc < T > {
105- #[ inline]
106- fn equals ( & self , other : & Rc < T > ) -> bool {
107- unsafe { ( * self . ptr ) . value . equals ( & ( * other. ptr ) . value ) }
108- }
110+ #[ inline( always) ]
111+ fn ne ( & self , other : & Rc < T > ) -> bool { * self . borrow ( ) != * other. borrow ( ) }
109112}
110113
111114impl < T : Ord > Ord for Rc < T > {
112- #[ inline]
113- fn lt ( & self , other : & Rc < T > ) -> bool {
114- unsafe { ( * self . ptr ) . value < ( * other. ptr ) . value }
115- }
115+ #[ inline( always) ]
116+ fn lt ( & self , other : & Rc < T > ) -> bool { * self . borrow ( ) < * other. borrow ( ) }
116117
117- #[ inline]
118- fn le ( & self , other : & Rc < T > ) -> bool {
119- unsafe { ( * self . ptr ) . value <= ( * other. ptr ) . value }
120- }
118+ #[ inline( always) ]
119+ fn le ( & self , other : & Rc < T > ) -> bool { * self . borrow ( ) <= * other. borrow ( ) }
121120
122- #[ inline]
123- fn ge ( & self , other : & Rc < T > ) -> bool {
124- unsafe { ( * self . ptr ) . value >= ( * other. ptr ) . value }
125- }
121+ #[ inline( always) ]
122+ fn gt ( & self , other : & Rc < T > ) -> bool { * self . borrow ( ) > * other. borrow ( ) }
126123
127- #[ inline]
128- fn gt ( & self , other : & Rc < T > ) -> bool {
129- unsafe { ( * self . ptr ) . value > ( * other. ptr ) . value }
130- }
124+ #[ inline( always) ]
125+ fn ge ( & self , other : & Rc < T > ) -> bool { * self . borrow ( ) >= * other. borrow ( ) }
131126}
132127
133- impl < T : TotalOrd > TotalOrd for Rc < T > {
134- # [ inline ]
135- fn cmp ( & self , other : & Rc < T > ) -> Ordering {
136- unsafe { ( * self . ptr ) . value . cmp ( & ( * other . ptr ) . value ) }
137- }
128+ /// Weak reference to a reference-counted box
129+ # [ unsafe_no_drop_flag ]
130+ # [ no_send ]
131+ pub struct Weak < T > {
132+ priv ptr : * mut RcBox < T >
138133}
139134
140- impl < T > Clone for Rc < T > {
141- # [ inline ]
142- fn clone ( & self ) -> Rc < T > {
135+ impl < T > Weak < T > {
136+ /// Upgrade a weak reference to a strong reference
137+ pub fn upgrade ( & self ) -> Option < Rc < T > > {
143138 unsafe {
144- ( * self . ptr ) . count += 1 ;
145- Rc { ptr : self . ptr }
139+ if ( * self . ptr ) . strong == 0 {
140+ None
141+ } else {
142+ ( * self . ptr ) . strong += 1 ;
143+ Some ( Rc { ptr : self . ptr } )
144+ }
146145 }
147146 }
148147}
149148
150- impl < T : DeepClone > DeepClone for Rc < T > {
151- #[ inline]
152- fn deep_clone ( & self ) -> Rc < T > {
153- unsafe { Rc :: new_unchecked ( self . borrow ( ) . deep_clone ( ) ) }
154- }
155- }
156-
157149#[ unsafe_destructor]
158- impl < T > Drop for Rc < T > {
150+ impl < T > Drop for Weak < T > {
159151 fn drop ( & mut self ) {
160152 unsafe {
161- if self . ptr . is_not_null ( ) {
162- ( * self . ptr ) . count -= 1 ;
163- if ( * self . ptr ) . count == 0 {
164- let _ : ~ RcBox < T > = transmute ( self . ptr ) ;
153+ if self . ptr != 0 as * mut RcBox < T > {
154+ ( * self . ptr ) . weak -= 1 ;
155+ if ( * self . ptr ) . weak == 0 && ( * self . ptr ) . strong == 0 {
156+ exchange_free ( self . ptr as * mut u8 as * i8 )
165157 }
166158 }
167159 }
168160 }
169161}
170162
163+ impl < T > Clone for Weak < T > {
164+ #[ inline]
165+ fn clone ( & self ) -> Weak < T > {
166+ unsafe {
167+ ( * self . ptr ) . weak += 1 ;
168+ Weak { ptr : self . ptr }
169+ }
170+ }
171+ }
172+
171173#[ cfg( test) ]
172- mod test_rc {
174+ mod tests {
173175 use prelude:: * ;
174176 use super :: * ;
175177 use cell:: RefCell ;
176178
177179 #[ test]
178180 fn test_clone ( ) {
179- let x = Rc :: from_send ( RefCell :: new ( 5 ) ) ;
181+ let x = Rc :: new ( RefCell :: new ( 5 ) ) ;
180182 let y = x. clone ( ) ;
181183 x. borrow ( ) . with_mut ( |inner| {
182184 * inner = 20 ;
@@ -186,7 +188,7 @@ mod test_rc {
186188
187189 #[ test]
188190 fn test_deep_clone ( ) {
189- let x = Rc :: from_send ( RefCell :: new ( 5 ) ) ;
191+ let x = Rc :: new ( RefCell :: new ( 5 ) ) ;
190192 let y = x. deep_clone ( ) ;
191193 x. borrow ( ) . with_mut ( |inner| {
192194 * inner = 20 ;
@@ -210,13 +212,22 @@ mod test_rc {
210212
211213 #[ test]
212214 fn test_destructor ( ) {
213- let x = Rc :: from_send ( ~5 ) ;
215+ let x = Rc :: new ( ~5 ) ;
214216 assert_eq ! ( * * x. borrow( ) , 5 ) ;
215217 }
216218
217219 #[ test]
218- fn test_from_mut ( ) {
219- let a = 10 ;
220- let _x = Rc :: from_mut ( RefCell :: new ( & a) ) ;
220+ fn test_live ( ) {
221+ let x = Rc :: new ( 5 ) ;
222+ let y = x. downgrade ( ) ;
223+ assert ! ( y. upgrade( ) . is_some( ) ) ;
224+ }
225+
226+ #[ test]
227+ fn test_dead ( ) {
228+ let x = Rc :: new ( 5 ) ;
229+ let y = x. downgrade ( ) ;
230+ drop ( x) ;
231+ assert ! ( y. upgrade( ) . is_none( ) ) ;
221232 }
222233}
0 commit comments