From 4702667a62be3286828e2c43094cbfbcfd26ad2a Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Wed, 15 May 2013 18:06:22 -0400 Subject: [PATCH] allow constructing Rc/RcMut from Const types too --- src/libstd/rc.rs | 108 +++++++++++++++++++++++++++++------------------ 1 file changed, 66 insertions(+), 42 deletions(-) diff --git a/src/libstd/rc.rs b/src/libstd/rc.rs index cb0798f2a39..46f50eafec1 100644 --- a/src/libstd/rc.rs +++ b/src/libstd/rc.rs @@ -11,7 +11,11 @@ /** Task-local reference counted smart pointers 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` or `RcMut` is ever `Owned` and `RcMut` is never `Const`. If `T` is `Const`, a +cycle cannot be created with `Rc` because there is no way to modify it after creation. */ @@ -30,16 +34,26 @@ pub struct Rc { priv ptr: *mut RcBox, } -pub impl Rc { - fn new(value: T) -> Rc { - unsafe { - let ptr = malloc(sys::size_of::>() as size_t) as *mut RcBox; - assert!(!ptr::is_null(ptr)); - intrinsics::move_val_init(&mut *ptr, RcBox{value: value, count: 1}); - Rc{ptr: ptr} - } +priv impl Rc { + unsafe fn new(value: T) -> Rc { + let ptr = malloc(sys::size_of::>() as size_t) as *mut RcBox; + assert!(!ptr::is_null(ptr)); + intrinsics::move_val_init(&mut *ptr, RcBox{value: value, count: 1}); + Rc{ptr: ptr} } +} +// FIXME: #6516: should be a static method +pub fn rc_from_owned(value: T) -> Rc { + unsafe { Rc::new(value) } +} + +// FIXME: #6516: should be a static method +pub fn rc_from_const(value: T) -> Rc { + unsafe { Rc::new(value) } +} + +pub impl Rc { #[inline(always)] fn borrow<'r>(&'r self) -> &'r T { unsafe { cast::copy_lifetime(self, &(*self.ptr).value) } @@ -48,7 +62,7 @@ pub impl Rc { #[unsafe_destructor] #[cfg(not(stage0))] -impl Drop for Rc { +impl Drop for Rc { fn finalize(&self) { unsafe { (*self.ptr).count -= 1; @@ -62,7 +76,7 @@ impl Drop for Rc { #[unsafe_destructor] #[cfg(stage0)] -impl Drop for Rc { +impl Drop for Rc { fn finalize(&self) { unsafe { (*self.ptr).count -= 1; @@ -75,7 +89,7 @@ impl Drop for Rc { } -impl Clone for Rc { +impl Clone for Rc { /// Return a shallow copy of the reference counted pointer. #[inline] fn clone(&self) -> Rc { @@ -86,11 +100,11 @@ impl Clone for Rc { } } -impl DeepClone for Rc { +impl DeepClone for Rc { /// Return a deep copy of the reference counted pointer. #[inline] fn deep_clone(&self) -> Rc { - Rc::new(self.borrow().deep_clone()) + unsafe { Rc::new(self.borrow().deep_clone()) } } } @@ -101,7 +115,7 @@ mod test_rc { #[test] fn test_clone() { - let x = Rc::new(Cell(5)); + let x = rc_from_owned(Cell(5)); let y = x.clone(); do x.borrow().with_mut_ref |inner| { *inner = 20; @@ -111,7 +125,7 @@ mod test_rc { #[test] fn test_deep_clone() { - let x = Rc::new(Cell(5)); + let x = rc_from_owned(Cell(5)); let y = x.deep_clone(); do x.borrow().with_mut_ref |inner| { *inner = 20; @@ -121,13 +135,13 @@ mod test_rc { #[test] fn test_simple() { - let x = Rc::new(5); + let x = rc_from_const(5); assert_eq!(*x.borrow(), 5); } #[test] fn test_simple_clone() { - let x = Rc::new(5); + let x = rc_from_const(5); let y = x.clone(); assert_eq!(*x.borrow(), 5); assert_eq!(*y.borrow(), 5); @@ -135,7 +149,7 @@ mod test_rc { #[test] fn test_destructor() { - let x = Rc::new(~5); + let x = rc_from_owned(~5); assert_eq!(**x.borrow(), 5); } } @@ -167,16 +181,26 @@ pub struct RcMut { priv ptr: *mut RcMutBox, } -pub impl RcMut { - fn new(value: T) -> RcMut { - unsafe { - let ptr = malloc(sys::size_of::>() as size_t) as *mut RcMutBox; - assert!(!ptr::is_null(ptr)); - intrinsics::move_val_init(&mut *ptr, RcMutBox{value: value, count: 1, borrow: Nothing}); - RcMut{ptr: ptr} - } +priv impl RcMut { + unsafe fn new(value: T) -> RcMut { + let ptr = malloc(sys::size_of::>() as size_t) as *mut RcMutBox; + assert!(!ptr::is_null(ptr)); + intrinsics::move_val_init(&mut *ptr, RcMutBox{value: value, count: 1, borrow: Nothing}); + RcMut{ptr: ptr} } +} +// FIXME: #6516: should be a static method +pub fn rc_mut_from_owned(value: T) -> RcMut { + unsafe { RcMut::new(value) } +} + +// FIXME: #6516: should be a static method +pub fn rc_mut_from_const(value: T) -> RcMut { + unsafe { RcMut::new(value) } +} + +pub impl RcMut { /// Fails if there is already a mutable borrow of the box #[inline] fn with_borrow(&self, f: &fn(&T) -> U) -> U { @@ -205,7 +229,7 @@ pub impl RcMut { #[unsafe_destructor] #[cfg(not(stage0))] -impl Drop for RcMut { +impl Drop for RcMut { fn finalize(&self) { unsafe { (*self.ptr).count -= 1; @@ -219,7 +243,7 @@ impl Drop for RcMut { #[unsafe_destructor] #[cfg(stage0)] -impl Drop for RcMut { +impl Drop for RcMut { fn finalize(&self) { unsafe { (*self.ptr).count -= 1; @@ -231,7 +255,7 @@ impl Drop for RcMut { } } -impl Clone for RcMut { +impl Clone for RcMut { /// Return a shallow copy of the reference counted pointer. #[inline] fn clone(&self) -> RcMut { @@ -242,13 +266,13 @@ impl Clone for RcMut { } } -impl DeepClone for RcMut { +impl DeepClone for RcMut { /// Return a deep copy of the reference counted pointer. #[inline] fn deep_clone(&self) -> RcMut { do self.with_borrow |x| { // 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] fn test_clone() { - let x = RcMut::new(5); + let x = rc_mut_from_owned(5); let y = x.clone(); do x.with_mut_borrow |value| { *value = 20; @@ -271,7 +295,7 @@ mod test_rc_mut { #[test] fn test_deep_clone() { - let x = RcMut::new(5); + let x = rc_mut_from_const(5); let y = x.deep_clone(); do x.with_mut_borrow |value| { *value = 20; @@ -283,7 +307,7 @@ mod test_rc_mut { #[test] fn borrow_many() { - let x = RcMut::new(5); + let x = rc_mut_from_owned(5); let y = x.clone(); do x.with_borrow |a| { @@ -299,7 +323,7 @@ mod test_rc_mut { #[test] fn modify() { - let x = RcMut::new(5); + let x = rc_mut_from_const(5); let y = x.clone(); do y.with_mut_borrow |a| { @@ -314,14 +338,14 @@ mod test_rc_mut { #[test] fn release_immutable() { - let x = RcMut::new(5); + let x = rc_mut_from_owned(5); do x.with_borrow |_| {} do x.with_mut_borrow |_| {} } #[test] fn release_mutable() { - let x = RcMut::new(5); + let x = rc_mut_from_const(5); do x.with_mut_borrow |_| {} do x.with_borrow |_| {} } @@ -329,7 +353,7 @@ mod test_rc_mut { #[test] #[should_fail] fn frozen() { - let x = RcMut::new(5); + let x = rc_mut_from_owned(5); let y = x.clone(); do x.with_borrow |_| { @@ -341,7 +365,7 @@ mod test_rc_mut { #[test] #[should_fail] fn mutable_dupe() { - let x = RcMut::new(5); + let x = rc_mut_from_const(5); let y = x.clone(); do x.with_mut_borrow |_| { @@ -353,7 +377,7 @@ mod test_rc_mut { #[test] #[should_fail] fn mutable_freeze() { - let x = RcMut::new(5); + let x = rc_mut_from_owned(5); let y = x.clone(); do x.with_mut_borrow |_| { @@ -365,7 +389,7 @@ mod test_rc_mut { #[test] #[should_fail] fn restore_freeze() { - let x = RcMut::new(5); + let x = rc_mut_from_const(5); let y = x.clone(); do x.with_borrow |_| {