Skip to content

Commit c5bcb22

Browse files
committed
rename Strong -> Rc, replacing rc with weak
1 parent 77cc1c5 commit c5bcb22

File tree

4 files changed

+103
-288
lines changed

4 files changed

+103
-288
lines changed

src/libextra/serialize.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,7 @@ impl<S:Encoder,T:Encodable<S>> Encodable<S> for Rc<T> {
413413
}
414414
}
415415

416-
impl<D:Decoder,T:Decodable<D> + NonManaged> Decodable<D> for Rc<T> {
416+
impl<D:Decoder,T:Decodable<D>> Decodable<D> for Rc<T> {
417417
#[inline]
418418
fn decode(d: &mut D) -> Rc<T> {
419419
Rc::new(Decodable::decode(d))

src/libstd/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,6 @@ pub mod owned;
121121
pub mod managed;
122122
pub mod borrow;
123123
pub mod rc;
124-
pub mod weak;
125124
pub mod gc;
126125

127126

src/libstd/rc.rs

Lines changed: 102 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,27 @@ The `Rc` type provides shared ownership of an immutable value. Destruction is de
1414
will occur as soon as the last owner is gone. It is marked as non-sendable because it avoids the
1515
overhead 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;
2127
use ops::Drop;
22-
use kinds::NonManaged;
28+
use cmp::{Eq, Ord};
2329
use clone::{Clone, DeepClone};
24-
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};
2533

2634
struct RcBox<T> {
2735
value: T,
28-
count: uint
36+
strong: uint,
37+
weak: uint
2938
}
3039

3140
/// Immutable reference counted pointer type
@@ -35,152 +44,149 @@ pub struct Rc<T> {
3544
priv ptr: *mut RcBox<T>
3645
}
3746

38-
impl<T: NonManaged> Rc<T> {
47+
impl<T> Rc<T> {
3948
/// Construct a new reference-counted box
40-
#[inline]
4149
pub fn new(value: T) -> Rc<T> {
4250
unsafe {
43-
Rc { ptr: transmute(~RcBox { value: value, count: 1 }) }
51+
Rc { ptr: transmute(~RcBox { value: value, strong: 1, weak: 0 }) }
4452
}
4553
}
4654
}
4755

4856
impl<T> Rc<T> {
4957
/// Borrow the value contained in the reference-counted box
50-
#[inline]
51-
pub fn borrow<'r>(&'r self) -> &'r T {
58+
#[inline(always)]
59+
pub fn borrow<'a>(&'a self) -> &'a T {
5260
unsafe { &(*self.ptr).value }
5361
}
5462

55-
/// Determine if two reference-counted pointers point to the same object
56-
#[inline]
57-
pub fn ptr_eq(&self, other: &Rc<T>) -> bool {
58-
self.ptr == other.ptr
63+
/// Downgrade the reference-counted pointer to a weak reference
64+
pub fn downgrade(&self) -> Weak<T> {
65+
unsafe {
66+
(*self.ptr).weak += 1;
67+
Weak { ptr: self.ptr }
68+
}
5969
}
6070
}
6171

62-
impl<T: Eq> Eq for Rc<T> {
63-
#[inline]
64-
fn eq(&self, other: &Rc<T>) -> bool {
65-
unsafe { (*self.ptr).value == (*other.ptr).value }
72+
#[unsafe_destructor]
73+
impl<T> Drop for Rc<T> {
74+
fn drop(&mut self) {
75+
unsafe {
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+
}
85+
}
6686
}
87+
}
6788

89+
impl<T> Clone for Rc<T> {
6890
#[inline]
69-
fn ne(&self, other: &Rc<T>) -> bool {
70-
unsafe { (*self.ptr).value != (*other.ptr).value }
91+
fn clone(&self) -> Rc<T> {
92+
unsafe {
93+
(*self.ptr).strong += 1;
94+
Rc { ptr: self.ptr }
95+
}
7196
}
7297
}
7398

74-
impl<T: TotalEq> TotalEq for Rc<T> {
99+
impl<T: DeepClone> DeepClone for Rc<T> {
75100
#[inline]
76-
fn equals(&self, other: &Rc<T>) -> bool {
77-
unsafe { (*self.ptr).value.equals(&(*other.ptr).value) }
101+
fn deep_clone(&self) -> Rc<T> {
102+
Rc::new(self.borrow().deep_clone())
78103
}
79104
}
80105

106+
impl<T: Eq> Eq for Rc<T> {
107+
#[inline(always)]
108+
fn eq(&self, other: &Rc<T>) -> bool { *self.borrow() == *other.borrow() }
109+
110+
#[inline(always)]
111+
fn ne(&self, other: &Rc<T>) -> bool { *self.borrow() != *other.borrow() }
112+
}
113+
81114
impl<T: Ord> Ord for Rc<T> {
82-
#[inline]
83-
fn lt(&self, other: &Rc<T>) -> bool {
84-
unsafe { (*self.ptr).value < (*other.ptr).value }
85-
}
115+
#[inline(always)]
116+
fn lt(&self, other: &Rc<T>) -> bool { *self.borrow() < *other.borrow() }
86117

87-
#[inline]
88-
fn le(&self, other: &Rc<T>) -> bool {
89-
unsafe { (*self.ptr).value <= (*other.ptr).value }
90-
}
118+
#[inline(always)]
119+
fn le(&self, other: &Rc<T>) -> bool { *self.borrow() <= *other.borrow() }
91120

92-
#[inline]
93-
fn ge(&self, other: &Rc<T>) -> bool {
94-
unsafe { (*self.ptr).value >= (*other.ptr).value }
95-
}
121+
#[inline(always)]
122+
fn gt(&self, other: &Rc<T>) -> bool { *self.borrow() > *other.borrow() }
96123

97-
#[inline]
98-
fn gt(&self, other: &Rc<T>) -> bool {
99-
unsafe { (*self.ptr).value > (*other.ptr).value }
100-
}
124+
#[inline(always)]
125+
fn ge(&self, other: &Rc<T>) -> bool { *self.borrow() >= *other.borrow() }
101126
}
102127

103-
impl<T: TotalOrd> TotalOrd for Rc<T> {
104-
#[inline]
105-
fn cmp(&self, other: &Rc<T>) -> Ordering {
106-
unsafe { (*self.ptr).value.cmp(&(*other.ptr).value) }
107-
}
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>
108133
}
109134

110-
impl<T> Clone for Rc<T> {
111-
#[inline]
112-
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>> {
113138
unsafe {
114-
(*self.ptr).count += 1;
115-
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+
}
116145
}
117146
}
118147
}
119148

120-
impl<T: NonManaged + DeepClone> DeepClone for Rc<T> {
121-
#[inline]
122-
fn deep_clone(&self) -> Rc<T> {
123-
Rc::new(self.borrow().deep_clone())
124-
}
125-
}
126-
127149
#[unsafe_destructor]
128-
impl<T> Drop for Rc<T> {
150+
impl<T> Drop for Weak<T> {
129151
fn drop(&mut self) {
130152
unsafe {
131-
if self.ptr.is_not_null() {
132-
(*self.ptr).count -= 1;
133-
if (*self.ptr).count == 0 {
134-
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)
135157
}
136158
}
137159
}
138160
}
139161
}
140162

141-
#[cfg(test)]
142-
mod test_rc {
143-
use prelude::*;
144-
use super::*;
145-
use cell::RefCell;
146-
147-
#[test]
148-
fn test_clone() {
149-
let x = Rc::new(RefCell::new(5));
150-
let y = x.clone();
151-
x.borrow().with_mut(|inner| {
152-
*inner = 20;
153-
});
154-
assert_eq!(y.borrow().with(|v| *v), 20);
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+
}
155170
}
171+
}
156172

157-
#[test]
158-
fn test_deep_clone() {
159-
let x = Rc::new(RefCell::new(5));
160-
let y = x.deep_clone();
161-
x.borrow().with_mut(|inner| {
162-
*inner = 20;
163-
});
164-
assert_eq!(y.borrow().with(|v| *v), 5);
165-
}
173+
#[cfg(test)]
174+
mod tests {
175+
use super::*;
176+
use prelude::drop;
166177

167178
#[test]
168-
fn test_simple() {
179+
fn test_live() {
169180
let x = Rc::new(5);
170-
assert_eq!(*x.borrow(), 5);
181+
let y = x.downgrade();
182+
assert!(y.upgrade().is_some());
171183
}
172184

173185
#[test]
174-
fn test_simple_clone() {
186+
fn test_dead() {
175187
let x = Rc::new(5);
176-
let y = x.clone();
177-
assert_eq!(*x.borrow(), 5);
178-
assert_eq!(*y.borrow(), 5);
179-
}
180-
181-
#[test]
182-
fn test_destructor() {
183-
let x = Rc::new(~5);
184-
assert_eq!(**x.borrow(), 5);
188+
let y = x.downgrade();
189+
drop(x);
190+
assert!(y.upgrade().is_none());
185191
}
186192
}

0 commit comments

Comments
 (0)