Skip to content

Commit 28ddc65

Browse files
committed
auto merge of #10926 : thestinger/rust/rc, r=cmr
2 parents ff3d5d4 + fc60ace commit 28ddc65

File tree

7 files changed

+113
-123
lines changed

7 files changed

+113
-123
lines changed

src/libextra/serialize.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -406,14 +406,14 @@ impl<S:Encoder,T:Encodable<S>> Encodable<S> for @T {
406406
}
407407
}
408408

409-
impl<S:Encoder,T:Encodable<S> + Freeze> Encodable<S> for Rc<T> {
409+
impl<S:Encoder,T:Encodable<S>> Encodable<S> for Rc<T> {
410410
#[inline]
411411
fn encode(&self, s: &mut S) {
412412
self.borrow().encode(s)
413413
}
414414
}
415415

416-
impl<D:Decoder,T:Decodable<D> + Freeze> 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/librustuv/idle.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ mod test {
127127
}
128128

129129
fn mk(v: uint) -> (~IdleWatcher, Chan) {
130-
let rc = Rc::from_send(RefCell::new((None, 0)));
130+
let rc = Rc::new(RefCell::new((None, 0)));
131131
let cb = ~MyCallback(rc.clone(), v);
132132
let cb = cb as ~Callback:;
133133
let cb = unsafe { cast::transmute(cb) };

src/libstd/option.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -509,7 +509,7 @@ mod tests {
509509
}
510510
}
511511

512-
let i = Rc::from_send(RefCell::new(0));
512+
let i = Rc::new(RefCell::new(0));
513513
{
514514
let x = R(i.clone());
515515
let opt = Some(x);

src/libstd/rc.rs

+107-96
Original file line numberDiff line numberDiff line change
@@ -14,19 +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::{Freeze, Send};
28+
use cmp::{Eq, Ord};
2329
use 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

2734
struct 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

92106
impl<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

111114
impl<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
}

src/test/compile-fail/issue-7013.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ struct A
3737
fn main()
3838
{
3939
let a = A {v: ~B{v: None} as ~Foo}; //~ ERROR cannot pack type `~B`, which does not fulfill `Send`
40-
let v = Rc::from_send(RefCell::new(a));
40+
let v = Rc::new(RefCell::new(a));
4141
let w = v.clone();
4242
let b = v.borrow();
4343
let mut b = b.borrow_mut();

src/test/compile-fail/no_freeze-rc.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,6 @@ use std::cell::RefCell;
1414
fn bar<T: Freeze>(_: T) {}
1515

1616
fn main() {
17-
let x = Rc::from_send(RefCell::new(5));
17+
let x = Rc::new(RefCell::new(5));
1818
bar(x); //~ ERROR instantiating a type parameter with an incompatible type `std::rc::Rc<std::cell::RefCell<int>>`, which does not fulfill `Freeze`
1919
}

src/test/compile-fail/rcmut-not-const-and-not-owned.rs

-21
This file was deleted.

0 commit comments

Comments
 (0)