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.
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.
11 /*! Task-local reference counted boxes with weak pointer support
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.
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.
27 use clone::{Clone, DeepClone};
28 use rt::global_heap::exchange_free;
30 use option::{Option, Some, None};
38 /// Immutable reference counted pointer type
39 #[unsafe_no_drop_flag]
41 pub struct Strong<T> {
42 priv ptr: *mut RcBox<T>
46 /// Construct a new reference-counted box
47 pub fn new(value: T) -> Strong<T> {
49 Strong { ptr: transmute(~RcBox { value: value, strong: 1, weak: 0 }) }
55 /// Borrow the value contained in the reference-counted box
57 pub fn borrow<'a>(&'a self) -> &'a T {
58 unsafe { &(*self.ptr).value }
61 /// Downgrade the reference-counted pointer to a weak reference
62 pub fn downgrade(&self) -> Weak<T> {
64 (*self.ptr).weak += 1;
65 Weak { ptr: self.ptr }
71 impl<T> Drop for Strong<T> {
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)
87 impl<T> Clone for Strong<T> {
89 fn clone(&self) -> Strong<T> {
91 (*self.ptr).strong += 1;
92 Strong { ptr: self.ptr }
97 impl<T: DeepClone> DeepClone for Strong<T> {
99 fn deep_clone(&self) -> Strong<T> {
100 Strong::new(self.borrow().deep_clone())
104 impl<T: Eq> Eq for Strong<T> {
106 fn eq(&self, other: &Strong<T>) -> bool { *self.borrow() == *other.borrow() }
109 fn ne(&self, other: &Strong<T>) -> bool { *self.borrow() != *other.borrow() }
112 impl<T: Ord> Ord for Strong<T> {
114 fn lt(&self, other: &Strong<T>) -> bool { *self.borrow() < *other.borrow() }
117 fn le(&self, other: &Strong<T>) -> bool { *self.borrow() <= *other.borrow() }
120 fn gt(&self, other: &Strong<T>) -> bool { *self.borrow() > *other.borrow() }
123 fn ge(&self, other: &Strong<T>) -> bool { *self.borrow() >= *other.borrow() }
126 /// Weak reference to a reference-counted box
127 #[unsafe_no_drop_flag]
130 priv ptr: *mut RcBox<T>
134 /// Upgrade a weak reference to a strong reference
135 pub fn upgrade(&self) -> Option<Strong<T>> {
137 if (*self.ptr).strong == 0 {
140 (*self.ptr).strong += 1;
141 Some(Strong { ptr: self.ptr })
148 impl<T> Drop for Weak<T> {
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)
161 impl<T> Clone for Weak<T> {
163 fn clone(&self) -> Weak<T> {
165 (*self.ptr).weak += 1;
166 Weak { ptr: self.ptr }
178 let x = Strong::new(5);
179 let y = x.downgrade();
180 assert!(y.upgrade().is_some());
185 let x = Strong::new(5);
186 let y = x.downgrade();
188 assert!(y.upgrade().is_none());