Skip to content

Commit 9c412c5

Browse files
committed
---
yaml --- r: 148155 b: refs/heads/try2 c: 77cc1c5 h: refs/heads/master i: 148153: 76ec022 148151: 3a22910 v: v3
1 parent 75ec346 commit 9c412c5

File tree

3 files changed

+192
-1
lines changed

3 files changed

+192
-1
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ refs/heads/snap-stage3: 78a7676898d9f80ab540c6df5d4c9ce35bb50463
55
refs/heads/try: 519addf6277dbafccbb4159db4b710c37eaa2ec5
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b
8-
refs/heads/try2: b36a948831f7375b725f26ebec1df88687fdfeab
8+
refs/heads/try2: 77cc1c5107ced596b694265d898194f33ace361e
99
refs/heads/dist-snap: ba4081a5a8573875fed17545846f6f6902c8ba8d
1010
refs/tags/release-0.2: c870d2dffb391e14efb05aa27898f1f6333a9596
1111
refs/tags/release-0.3: b5f0d0f648d9a6153664837026ba1be43d3e2503

branches/try2/src/libstd/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ pub mod owned;
121121
pub mod managed;
122122
pub mod borrow;
123123
pub mod rc;
124+
pub mod weak;
124125
pub mod gc;
125126

126127

branches/try2/src/libstd/weak.rs

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
/*! Task-local reference counted boxes with weak pointer support
12+
13+
The `Strong` type is an extension of `std::rc::Rc` with a `downgrade` method returning a `Weak`
14+
pointer type. Ownership of the contained value is shared amongst the `Strong` pointers, and the
15+
value will be destroyed as soon as the last one is gone. A `Weak` pointer can be upgraded to a
16+
`Strong` pointer, but will return `None` if the value has already been freed. It can be used to
17+
avoid creating reference cycles.
18+
19+
For example, a tree with parent pointers can be represented by putting the nodes behind `Strong`
20+
pointers, and then storing the parent pointers as `Weak` pointers.
21+
22+
*/
23+
24+
use cast::transmute;
25+
use ops::Drop;
26+
use cmp::{Eq, Ord};
27+
use clone::{Clone, DeepClone};
28+
use rt::global_heap::exchange_free;
29+
use ptr::read_ptr;
30+
use option::{Option, Some, None};
31+
32+
struct RcBox<T> {
33+
value: T,
34+
strong: uint,
35+
weak: uint
36+
}
37+
38+
/// Immutable reference counted pointer type
39+
#[unsafe_no_drop_flag]
40+
#[no_send]
41+
pub struct Strong<T> {
42+
priv ptr: *mut RcBox<T>
43+
}
44+
45+
impl<T> Strong<T> {
46+
/// Construct a new reference-counted box
47+
pub fn new(value: T) -> Strong<T> {
48+
unsafe {
49+
Strong { ptr: transmute(~RcBox { value: value, strong: 1, weak: 0 }) }
50+
}
51+
}
52+
}
53+
54+
impl<T> Strong<T> {
55+
/// Borrow the value contained in the reference-counted box
56+
#[inline(always)]
57+
pub fn borrow<'a>(&'a self) -> &'a T {
58+
unsafe { &(*self.ptr).value }
59+
}
60+
61+
/// Downgrade the reference-counted pointer to a weak reference
62+
pub fn downgrade(&self) -> Weak<T> {
63+
unsafe {
64+
(*self.ptr).weak += 1;
65+
Weak { ptr: self.ptr }
66+
}
67+
}
68+
}
69+
70+
#[unsafe_destructor]
71+
impl<T> Drop for Strong<T> {
72+
fn drop(&mut self) {
73+
unsafe {
74+
if self.ptr != 0 as *mut RcBox<T> {
75+
(*self.ptr).strong -= 1;
76+
if (*self.ptr).strong == 0 {
77+
read_ptr(self.borrow()); // destroy the contained object
78+
if (*self.ptr).weak == 0 {
79+
exchange_free(self.ptr as *mut u8 as *i8)
80+
}
81+
}
82+
}
83+
}
84+
}
85+
}
86+
87+
impl<T> Clone for Strong<T> {
88+
#[inline]
89+
fn clone(&self) -> Strong<T> {
90+
unsafe {
91+
(*self.ptr).strong += 1;
92+
Strong { ptr: self.ptr }
93+
}
94+
}
95+
}
96+
97+
impl<T: DeepClone> DeepClone for Strong<T> {
98+
#[inline]
99+
fn deep_clone(&self) -> Strong<T> {
100+
Strong::new(self.borrow().deep_clone())
101+
}
102+
}
103+
104+
impl<T: Eq> Eq for Strong<T> {
105+
#[inline(always)]
106+
fn eq(&self, other: &Strong<T>) -> bool { *self.borrow() == *other.borrow() }
107+
108+
#[inline(always)]
109+
fn ne(&self, other: &Strong<T>) -> bool { *self.borrow() != *other.borrow() }
110+
}
111+
112+
impl<T: Ord> Ord for Strong<T> {
113+
#[inline(always)]
114+
fn lt(&self, other: &Strong<T>) -> bool { *self.borrow() < *other.borrow() }
115+
116+
#[inline(always)]
117+
fn le(&self, other: &Strong<T>) -> bool { *self.borrow() <= *other.borrow() }
118+
119+
#[inline(always)]
120+
fn gt(&self, other: &Strong<T>) -> bool { *self.borrow() > *other.borrow() }
121+
122+
#[inline(always)]
123+
fn ge(&self, other: &Strong<T>) -> bool { *self.borrow() >= *other.borrow() }
124+
}
125+
126+
/// Weak reference to a reference-counted box
127+
#[unsafe_no_drop_flag]
128+
#[no_send]
129+
pub struct Weak<T> {
130+
priv ptr: *mut RcBox<T>
131+
}
132+
133+
impl<T> Weak<T> {
134+
/// Upgrade a weak reference to a strong reference
135+
pub fn upgrade(&self) -> Option<Strong<T>> {
136+
unsafe {
137+
if (*self.ptr).strong == 0 {
138+
None
139+
} else {
140+
(*self.ptr).strong += 1;
141+
Some(Strong { ptr: self.ptr })
142+
}
143+
}
144+
}
145+
}
146+
147+
#[unsafe_destructor]
148+
impl<T> Drop for Weak<T> {
149+
fn drop(&mut self) {
150+
unsafe {
151+
if self.ptr != 0 as *mut RcBox<T> {
152+
(*self.ptr).weak -= 1;
153+
if (*self.ptr).weak == 0 && (*self.ptr).strong == 0 {
154+
exchange_free(self.ptr as *mut u8 as *i8)
155+
}
156+
}
157+
}
158+
}
159+
}
160+
161+
impl<T> Clone for Weak<T> {
162+
#[inline]
163+
fn clone(&self) -> Weak<T> {
164+
unsafe {
165+
(*self.ptr).weak += 1;
166+
Weak { ptr: self.ptr }
167+
}
168+
}
169+
}
170+
171+
#[cfg(test)]
172+
mod tests {
173+
use super::*;
174+
use prelude::drop;
175+
176+
#[test]
177+
fn test_live() {
178+
let x = Strong::new(5);
179+
let y = x.downgrade();
180+
assert!(y.upgrade().is_some());
181+
}
182+
183+
#[test]
184+
fn test_dead() {
185+
let x = Strong::new(5);
186+
let y = x.downgrade();
187+
drop(x);
188+
assert!(y.upgrade().is_none());
189+
}
190+
}

0 commit comments

Comments
 (0)