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:
commit
ce6dc2451f
@ -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 |_| {
|
||||
|
Loading…
Reference in New Issue
Block a user