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 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>,
}
pub impl<T: Owned> Rc<T> {
fn new(value: T) -> Rc<T> {
unsafe {
priv impl<T> Rc<T> {
unsafe fn new(value: T) -> Rc<T> {
let ptr = malloc(sys::size_of::<RcBox<T>>() as size_t) as *mut RcBox<T>;
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<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)]
fn borrow<'r>(&'r self) -> &'r T {
unsafe { cast::copy_lifetime(self, &(*self.ptr).value) }
@ -48,7 +62,7 @@ pub impl<T: Owned> Rc<T> {
#[unsafe_destructor]
#[cfg(not(stage0))]
impl<T: Owned> Drop for Rc<T> {
impl<T> Drop for Rc<T> {
fn finalize(&self) {
unsafe {
(*self.ptr).count -= 1;
@ -62,7 +76,7 @@ impl<T: Owned> Drop for Rc<T> {
#[unsafe_destructor]
#[cfg(stage0)]
impl<T: Owned> Drop for Rc<T> {
impl<T> Drop for Rc<T> {
fn finalize(&self) {
unsafe {
(*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.
#[inline]
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.
#[inline]
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]
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<T> {
priv ptr: *mut RcMutBox<T>,
}
pub impl<T: Owned> RcMut<T> {
fn new(value: T) -> RcMut<T> {
unsafe {
priv impl<T> RcMut<T> {
unsafe fn new(value: T) -> RcMut<T> {
let ptr = malloc(sys::size_of::<RcMutBox<T>>() as size_t) as *mut RcMutBox<T>;
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<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
#[inline]
fn with_borrow<U>(&self, f: &fn(&T) -> U) -> U {
@ -205,7 +229,7 @@ pub impl<T: Owned> RcMut<T> {
#[unsafe_destructor]
#[cfg(not(stage0))]
impl<T: Owned> Drop for RcMut<T> {
impl<T> Drop for RcMut<T> {
fn finalize(&self) {
unsafe {
(*self.ptr).count -= 1;
@ -219,7 +243,7 @@ impl<T: Owned> Drop for RcMut<T> {
#[unsafe_destructor]
#[cfg(stage0)]
impl<T: Owned> Drop for RcMut<T> {
impl<T> Drop for RcMut<T> {
fn finalize(&self) {
unsafe {
(*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.
#[inline]
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.
#[inline]
fn deep_clone(&self) -> RcMut<T> {
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 |_| {