about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorDaniel Micay <danielmicay@gmail.com>2013-05-15 00:45:40 -0400
committerDaniel Micay <danielmicay@gmail.com>2013-05-15 01:36:41 -0400
commit75822f2894498025d6a86bcaf30fa56118c7d3ab (patch)
tree22210464695226860d71add6db6801634d775bc6 /src/libstd
parentfa45958ec8362c1157d8d655fc8ec95ba3f811d6 (diff)
downloadrust-75822f2894498025d6a86bcaf30fa56118c7d3ab.tar.gz
rust-75822f2894498025d6a86bcaf30fa56118c7d3ab.zip
add a DeepClone trait
for deep copies through shared ownership boundaries
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/rc.rs84
1 files changed, 80 insertions, 4 deletions
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<T: Owned> Drop for Rc<T> {
 
 
 impl<T: Owned> Clone for Rc<T> {
+    /// Return a shallow copy of the reference counted pointer.
     #[inline]
     fn clone(&self) -> Rc<T> {
         unsafe {
@@ -85,9 +86,46 @@ impl<T: Owned> Clone for Rc<T> {
     }
 }
 
+impl<T: Owned + 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())
+    }
+}
+
 #[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<T: Owned> RcMut<T> {
 
     /// Fails if there is already a mutable borrow of the box
     #[inline]
-    fn with_borrow(&self, f: &fn(&T)) {
+    fn with_borrow<U>(&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<U>(&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<T: Owned> Drop for RcMut<T> {
 }
 
 impl<T: Owned> Clone for RcMut<T> {
+    /// Return a shallow copy of the reference counted pointer.
     #[inline]
     fn clone(&self) -> RcMut<T> {
         unsafe {
@@ -209,11 +250,46 @@ impl<T: Owned> Clone for RcMut<T> {
     }
 }
 
+impl<T: Owned + 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())
+        }
+    }
+}
+
 #[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);
         let y = x.clone();