auto merge of #6520 : thestinger/rust/rc, r=pcwalton

This is still enough to prevent cycles (explanation given in the docstring).
This commit is contained in:
bors 2013-05-16 03:25:43 -07:00
commit ce6dc2451f

View File

@ -11,7 +11,11 @@
/** Task-local reference counted smart pointers /** Task-local reference counted smart pointers
Task-local reference counted smart pointers are an alternative to managed boxes with deterministic Task-local reference counted smart pointers are an alternative to managed boxes with deterministic
destruction. They are restricted to containing `Owned` types in order to prevent cycles. destruction. They are restricted to containing types that are either `Owned` or `Const` (or both) to
prevent cycles.
Neither `Rc<T>` or `RcMut<T>` is ever `Owned` and `RcMut<T>` is never `Const`. If `T` is `Const`, a
cycle cannot be created with `Rc<T>` because there is no way to modify it after creation.
*/ */
@ -30,16 +34,26 @@ pub struct Rc<T> {
priv ptr: *mut RcBox<T>, priv ptr: *mut RcBox<T>,
} }
pub impl<T: Owned> Rc<T> { priv impl<T> Rc<T> {
fn new(value: T) -> Rc<T> { unsafe fn new(value: T) -> Rc<T> {
unsafe { let ptr = malloc(sys::size_of::<RcBox<T>>() as size_t) as *mut RcBox<T>;
let ptr = malloc(sys::size_of::<RcBox<T>>() as size_t) as *mut RcBox<T>; assert!(!ptr::is_null(ptr));
assert!(!ptr::is_null(ptr)); intrinsics::move_val_init(&mut *ptr, RcBox{value: value, count: 1});
intrinsics::move_val_init(&mut *ptr, RcBox{value: value, count: 1}); Rc{ptr: ptr}
Rc{ptr: ptr}
}
} }
}
// FIXME: #6516: should be a static method
pub fn rc_from_owned<T: Owned>(value: T) -> Rc<T> {
unsafe { Rc::new(value) }
}
// FIXME: #6516: should be a static method
pub fn rc_from_const<T: Const>(value: T) -> Rc<T> {
unsafe { Rc::new(value) }
}
pub impl<T> Rc<T> {
#[inline(always)] #[inline(always)]
fn borrow<'r>(&'r self) -> &'r T { fn borrow<'r>(&'r self) -> &'r T {
unsafe { cast::copy_lifetime(self, &(*self.ptr).value) } unsafe { cast::copy_lifetime(self, &(*self.ptr).value) }
@ -48,7 +62,7 @@ pub impl<T: Owned> Rc<T> {
#[unsafe_destructor] #[unsafe_destructor]
#[cfg(not(stage0))] #[cfg(not(stage0))]
impl<T: Owned> Drop for Rc<T> { impl<T> Drop for Rc<T> {
fn finalize(&self) { fn finalize(&self) {
unsafe { unsafe {
(*self.ptr).count -= 1; (*self.ptr).count -= 1;
@ -62,7 +76,7 @@ impl<T: Owned> Drop for Rc<T> {
#[unsafe_destructor] #[unsafe_destructor]
#[cfg(stage0)] #[cfg(stage0)]
impl<T: Owned> Drop for Rc<T> { impl<T> Drop for Rc<T> {
fn finalize(&self) { fn finalize(&self) {
unsafe { unsafe {
(*self.ptr).count -= 1; (*self.ptr).count -= 1;
@ -75,7 +89,7 @@ impl<T: Owned> Drop for Rc<T> {
} }
impl<T: Owned> Clone for Rc<T> { impl<T> Clone for Rc<T> {
/// Return a shallow copy of the reference counted pointer. /// Return a shallow copy of the reference counted pointer.
#[inline] #[inline]
fn clone(&self) -> Rc<T> { fn clone(&self) -> Rc<T> {
@ -86,11 +100,11 @@ impl<T: Owned> Clone for Rc<T> {
} }
} }
impl<T: Owned + DeepClone> DeepClone for Rc<T> { impl<T: DeepClone> DeepClone for Rc<T> {
/// Return a deep copy of the reference counted pointer. /// Return a deep copy of the reference counted pointer.
#[inline] #[inline]
fn deep_clone(&self) -> Rc<T> { fn deep_clone(&self) -> Rc<T> {
Rc::new(self.borrow().deep_clone()) unsafe { Rc::new(self.borrow().deep_clone()) }
} }
} }
@ -101,7 +115,7 @@ mod test_rc {
#[test] #[test]
fn test_clone() { fn test_clone() {
let x = Rc::new(Cell(5)); let x = rc_from_owned(Cell(5));
let y = x.clone(); let y = x.clone();
do x.borrow().with_mut_ref |inner| { do x.borrow().with_mut_ref |inner| {
*inner = 20; *inner = 20;
@ -111,7 +125,7 @@ mod test_rc {
#[test] #[test]
fn test_deep_clone() { fn test_deep_clone() {
let x = Rc::new(Cell(5)); let x = rc_from_owned(Cell(5));
let y = x.deep_clone(); let y = x.deep_clone();
do x.borrow().with_mut_ref |inner| { do x.borrow().with_mut_ref |inner| {
*inner = 20; *inner = 20;
@ -121,13 +135,13 @@ mod test_rc {
#[test] #[test]
fn test_simple() { fn test_simple() {
let x = Rc::new(5); let x = rc_from_const(5);
assert_eq!(*x.borrow(), 5); assert_eq!(*x.borrow(), 5);
} }
#[test] #[test]
fn test_simple_clone() { fn test_simple_clone() {
let x = Rc::new(5); let x = rc_from_const(5);
let y = x.clone(); let y = x.clone();
assert_eq!(*x.borrow(), 5); assert_eq!(*x.borrow(), 5);
assert_eq!(*y.borrow(), 5); assert_eq!(*y.borrow(), 5);
@ -135,7 +149,7 @@ mod test_rc {
#[test] #[test]
fn test_destructor() { fn test_destructor() {
let x = Rc::new(~5); let x = rc_from_owned(~5);
assert_eq!(**x.borrow(), 5); assert_eq!(**x.borrow(), 5);
} }
} }
@ -167,16 +181,26 @@ pub struct RcMut<T> {
priv ptr: *mut RcMutBox<T>, priv ptr: *mut RcMutBox<T>,
} }
pub impl<T: Owned> RcMut<T> { priv impl<T> RcMut<T> {
fn new(value: T) -> RcMut<T> { unsafe fn new(value: T) -> RcMut<T> {
unsafe { let ptr = malloc(sys::size_of::<RcMutBox<T>>() as size_t) as *mut RcMutBox<T>;
let ptr = malloc(sys::size_of::<RcMutBox<T>>() as size_t) as *mut RcMutBox<T>; assert!(!ptr::is_null(ptr));
assert!(!ptr::is_null(ptr)); intrinsics::move_val_init(&mut *ptr, RcMutBox{value: value, count: 1, borrow: Nothing});
intrinsics::move_val_init(&mut *ptr, RcMutBox{value: value, count: 1, borrow: Nothing}); RcMut{ptr: ptr}
RcMut{ptr: ptr}
}
} }
}
// FIXME: #6516: should be a static method
pub fn rc_mut_from_owned<T: Owned>(value: T) -> RcMut<T> {
unsafe { RcMut::new(value) }
}
// FIXME: #6516: should be a static method
pub fn rc_mut_from_const<T: Const>(value: T) -> RcMut<T> {
unsafe { RcMut::new(value) }
}
pub impl<T> RcMut<T> {
/// Fails if there is already a mutable borrow of the box /// Fails if there is already a mutable borrow of the box
#[inline] #[inline]
fn with_borrow<U>(&self, f: &fn(&T) -> U) -> U { fn with_borrow<U>(&self, f: &fn(&T) -> U) -> U {
@ -205,7 +229,7 @@ pub impl<T: Owned> RcMut<T> {
#[unsafe_destructor] #[unsafe_destructor]
#[cfg(not(stage0))] #[cfg(not(stage0))]
impl<T: Owned> Drop for RcMut<T> { impl<T> Drop for RcMut<T> {
fn finalize(&self) { fn finalize(&self) {
unsafe { unsafe {
(*self.ptr).count -= 1; (*self.ptr).count -= 1;
@ -219,7 +243,7 @@ impl<T: Owned> Drop for RcMut<T> {
#[unsafe_destructor] #[unsafe_destructor]
#[cfg(stage0)] #[cfg(stage0)]
impl<T: Owned> Drop for RcMut<T> { impl<T> Drop for RcMut<T> {
fn finalize(&self) { fn finalize(&self) {
unsafe { unsafe {
(*self.ptr).count -= 1; (*self.ptr).count -= 1;
@ -231,7 +255,7 @@ impl<T: Owned> Drop for RcMut<T> {
} }
} }
impl<T: Owned> Clone for RcMut<T> { impl<T> Clone for RcMut<T> {
/// Return a shallow copy of the reference counted pointer. /// Return a shallow copy of the reference counted pointer.
#[inline] #[inline]
fn clone(&self) -> RcMut<T> { fn clone(&self) -> RcMut<T> {
@ -242,13 +266,13 @@ impl<T: Owned> Clone for RcMut<T> {
} }
} }
impl<T: Owned + DeepClone> DeepClone for RcMut<T> { impl<T: DeepClone> DeepClone for RcMut<T> {
/// Return a deep copy of the reference counted pointer. /// Return a deep copy of the reference counted pointer.
#[inline] #[inline]
fn deep_clone(&self) -> RcMut<T> { fn deep_clone(&self) -> RcMut<T> {
do self.with_borrow |x| { do self.with_borrow |x| {
// FIXME: #6497: should avoid freeze (slow) // FIXME: #6497: should avoid freeze (slow)
RcMut::new(x.deep_clone()) unsafe { RcMut::new(x.deep_clone()) }
} }
} }
} }
@ -259,7 +283,7 @@ mod test_rc_mut {
#[test] #[test]
fn test_clone() { fn test_clone() {
let x = RcMut::new(5); let x = rc_mut_from_owned(5);
let y = x.clone(); let y = x.clone();
do x.with_mut_borrow |value| { do x.with_mut_borrow |value| {
*value = 20; *value = 20;
@ -271,7 +295,7 @@ mod test_rc_mut {
#[test] #[test]
fn test_deep_clone() { fn test_deep_clone() {
let x = RcMut::new(5); let x = rc_mut_from_const(5);
let y = x.deep_clone(); let y = x.deep_clone();
do x.with_mut_borrow |value| { do x.with_mut_borrow |value| {
*value = 20; *value = 20;
@ -283,7 +307,7 @@ mod test_rc_mut {
#[test] #[test]
fn borrow_many() { fn borrow_many() {
let x = RcMut::new(5); let x = rc_mut_from_owned(5);
let y = x.clone(); let y = x.clone();
do x.with_borrow |a| { do x.with_borrow |a| {
@ -299,7 +323,7 @@ mod test_rc_mut {
#[test] #[test]
fn modify() { fn modify() {
let x = RcMut::new(5); let x = rc_mut_from_const(5);
let y = x.clone(); let y = x.clone();
do y.with_mut_borrow |a| { do y.with_mut_borrow |a| {
@ -314,14 +338,14 @@ mod test_rc_mut {
#[test] #[test]
fn release_immutable() { fn release_immutable() {
let x = RcMut::new(5); let x = rc_mut_from_owned(5);
do x.with_borrow |_| {} do x.with_borrow |_| {}
do x.with_mut_borrow |_| {} do x.with_mut_borrow |_| {}
} }
#[test] #[test]
fn release_mutable() { fn release_mutable() {
let x = RcMut::new(5); let x = rc_mut_from_const(5);
do x.with_mut_borrow |_| {} do x.with_mut_borrow |_| {}
do x.with_borrow |_| {} do x.with_borrow |_| {}
} }
@ -329,7 +353,7 @@ mod test_rc_mut {
#[test] #[test]
#[should_fail] #[should_fail]
fn frozen() { fn frozen() {
let x = RcMut::new(5); let x = rc_mut_from_owned(5);
let y = x.clone(); let y = x.clone();
do x.with_borrow |_| { do x.with_borrow |_| {
@ -341,7 +365,7 @@ mod test_rc_mut {
#[test] #[test]
#[should_fail] #[should_fail]
fn mutable_dupe() { fn mutable_dupe() {
let x = RcMut::new(5); let x = rc_mut_from_const(5);
let y = x.clone(); let y = x.clone();
do x.with_mut_borrow |_| { do x.with_mut_borrow |_| {
@ -353,7 +377,7 @@ mod test_rc_mut {
#[test] #[test]
#[should_fail] #[should_fail]
fn mutable_freeze() { fn mutable_freeze() {
let x = RcMut::new(5); let x = rc_mut_from_owned(5);
let y = x.clone(); let y = x.clone();
do x.with_mut_borrow |_| { do x.with_mut_borrow |_| {
@ -365,7 +389,7 @@ mod test_rc_mut {
#[test] #[test]
#[should_fail] #[should_fail]
fn restore_freeze() { fn restore_freeze() {
let x = RcMut::new(5); let x = rc_mut_from_const(5);
let y = x.clone(); let y = x.clone();
do x.with_borrow |_| { do x.with_borrow |_| {