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
108
src/libstd/rc.rs
108
src/libstd/rc.rs
@ -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 |_| {
|
||||||
|
Loading…
Reference in New Issue
Block a user