From 75822f2894498025d6a86bcaf30fa56118c7d3ab Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Wed, 15 May 2013 00:45:40 -0400 Subject: add a DeepClone trait for deep copies through shared ownership boundaries --- src/libstd/rc.rs | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 80 insertions(+), 4 deletions(-) (limited to 'src/libstd') diff --git a/src/libstd/rc.rs b/src/libstd/rc.rs index 8cf2da3a1e8..41fcc1d402e 100644 --- a/src/libstd/rc.rs +++ b/src/libstd/rc.rs @@ -76,6 +76,7 @@ impl Drop for Rc { impl Clone for Rc { + /// Return a shallow copy of the reference counted pointer. #[inline] fn clone(&self) -> Rc { unsafe { @@ -85,9 +86,46 @@ impl Clone 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()) + } +} + #[cfg(test)] mod test_rc { use super::*; + use core::cell::Cell; + + #[test] + fn test_clone() { + let x = Rc::new(Cell(5)); + let y = x.clone(); + do x.with_borrow |cell| { + do value.with_mut_ref |inner| { + *inner = 20; + } + } + do y.with_borrow |value| { + assert_eq!(value.take(), 20); + } + } + + #[test] + fn test_deep_clone() { + let x = Rc::new(Cell(5)); + let y = x.deep_clone(); + do x.with_borrow |cell| { + do value.with_mut_ref |inner| { + *inner = 20; + } + } + do y.with_borrow |value| { + assert_eq!(value.take(), 5); + } + } #[test] fn test_simple() { @@ -149,24 +187,26 @@ pub impl RcMut { /// Fails if there is already a mutable borrow of the box #[inline] - fn with_borrow(&self, f: &fn(&T)) { + fn with_borrow(&self, f: &fn(&T) -> U) -> U { unsafe { assert!((*self.ptr).borrow != Mutable); let previous = (*self.ptr).borrow; (*self.ptr).borrow = Immutable; - f(&(*self.ptr).value); + let res = f(&(*self.ptr).value); (*self.ptr).borrow = previous; + res } } /// Fails if there is already a mutable or immutable borrow of the box #[inline] - fn with_mut_borrow(&self, f: &fn(&mut T)) { + fn with_mut_borrow(&self, f: &fn(&mut T) -> U) -> U { unsafe { assert!((*self.ptr).borrow == Nothing); (*self.ptr).borrow = Mutable; - f(&mut (*self.ptr).value); + let res = f(&mut (*self.ptr).value); (*self.ptr).borrow = Nothing; + res } } } @@ -200,6 +240,7 @@ impl Drop for RcMut { } impl Clone for RcMut { + /// Return a shallow copy of the reference counted pointer. #[inline] fn clone(&self) -> RcMut { unsafe { @@ -209,10 +250,45 @@ impl Clone 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()) + } + } +} + #[cfg(test)] mod test_rc_mut { use super::*; + #[test] + fn test_clone() { + let x = RcMut::new(5); + let y = x.clone(); + do x.with_mut_borrow |value| { + *value = 20; + } + do y.with_borrow |value| { + assert_eq!(*value, 20); + } + } + + #[test] + fn test_deep_clone() { + let x = RcMut::new(5); + let y = x.deep_clone(); + do x.with_mut_borrow |value| { + *value = 20; + } + do y.with_borrow |value| { + assert_eq!(*value, 5); + } + } + #[test] fn borrow_many() { let x = RcMut::new(5); -- cgit 1.4.1-3-g733a5 From cda3ac905a56dc6580429eea259143d30a7f3c02 Mon Sep 17 00:00:00 2001 From: Daniel Micay Date: Wed, 15 May 2013 02:23:12 -0400 Subject: rc: fix tests --- src/libcore/cell.rs | 7 +++++++ src/libcore/option.rs | 10 ++++++++++ src/libstd/rc.rs | 22 +++++++--------------- 3 files changed, 24 insertions(+), 15 deletions(-) (limited to 'src/libstd') diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index cacde5535db..87e8d0525e5 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -21,10 +21,17 @@ Similar to a mutable option type, but friendlier. */ #[mutable] +#[deriving(Clone)] pub struct Cell { priv value: Option } +impl DeepClone for Cell { + fn deep_clone(&self) -> Cell { + Cell{value: self.value.deep_clone()} + } +} + impl cmp::Eq for Cell { fn eq(&self, other: &Cell) -> bool { (self.value) == (other.value) diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 9aaa2921fe7..5aee3077e48 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -49,6 +49,7 @@ use num::Zero; use old_iter::{BaseIter, MutableIter, ExtendedIter}; use old_iter; use str::StrSlice; +use clone::DeepClone; #[cfg(test)] use str; @@ -59,6 +60,15 @@ pub enum Option { Some(T), } +impl DeepClone for Option { + fn deep_clone(&self) -> Option { + match *self { + Some(ref x) => Some(x.deep_clone()), + None => None + } + } +} + impl Ord for Option { fn lt(&self, other: &Option) -> bool { match (self, other) { diff --git a/src/libstd/rc.rs b/src/libstd/rc.rs index 41fcc1d402e..cb0798f2a39 100644 --- a/src/libstd/rc.rs +++ b/src/libstd/rc.rs @@ -103,28 +103,20 @@ mod test_rc { fn test_clone() { let x = Rc::new(Cell(5)); let y = x.clone(); - do x.with_borrow |cell| { - do value.with_mut_ref |inner| { - *inner = 20; - } - } - do y.with_borrow |value| { - assert_eq!(value.take(), 20); + do x.borrow().with_mut_ref |inner| { + *inner = 20; } + assert_eq!(y.borrow().take(), 20); } #[test] fn test_deep_clone() { let x = Rc::new(Cell(5)); let y = x.deep_clone(); - do x.with_borrow |cell| { - do value.with_mut_ref |inner| { - *inner = 20; - } - } - do y.with_borrow |value| { - assert_eq!(value.take(), 5); + do x.borrow().with_mut_ref |inner| { + *inner = 20; } + assert_eq!(y.borrow().take(), 5); } #[test] @@ -134,7 +126,7 @@ mod test_rc { } #[test] - fn test_clone() { + fn test_simple_clone() { let x = Rc::new(5); let y = x.clone(); assert_eq!(*x.borrow(), 5); -- cgit 1.4.1-3-g733a5