about summary refs log tree commit diff
path: root/src/libcore
diff options
context:
space:
mode:
authorCorey Richardson <corey@octayn.net>2014-12-05 10:06:43 -0800
committerCorey Richardson <corey@octayn.net>2014-12-05 10:06:43 -0800
commitbe75f2e090f4a6bd3d649a98708aa4bc6a6a0692 (patch)
treec5843e26796f53d15ee08df1ff3864e41b2cbd0d /src/libcore
parentd066b5c4be0b49dd15f1bb6029c01f4cd298c19e (diff)
parent5048953debe9eb44c672f3c453e894bd64a1301a (diff)
downloadrust-be75f2e090f4a6bd3d649a98708aa4bc6a6a0692.tar.gz
rust-be75f2e090f4a6bd3d649a98708aa4bc6a6a0692.zip
rollup merge of #19386: tbu-/pr_refcell_stuff
Diffstat (limited to 'src/libcore')
-rw-r--r--src/libcore/cell.rs118
1 files changed, 75 insertions, 43 deletions
diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs
index 587bb4cb110..ed4df101202 100644
--- a/src/libcore/cell.rs
+++ b/src/libcore/cell.rs
@@ -277,12 +277,9 @@ impl<T> RefCell<T> {
     /// Returns `None` if the value is currently mutably borrowed.
     #[unstable = "may be renamed, depending on global conventions"]
     pub fn try_borrow<'a>(&'a self) -> Option<Ref<'a, T>> {
-        match self.borrow.get() {
-            WRITING => None,
-            borrow => {
-                self.borrow.set(borrow + 1);
-                Some(Ref { _parent: self })
-            }
+        match BorrowRef::new(&self.borrow) {
+            Some(b) => Some(Ref { _value: unsafe { &*self.value.get() }, _borrow: b }),
+            None => None,
         }
     }
 
@@ -310,12 +307,9 @@ impl<T> RefCell<T> {
     /// Returns `None` if the value is currently borrowed.
     #[unstable = "may be renamed, depending on global conventions"]
     pub fn try_borrow_mut<'a>(&'a self) -> Option<RefMut<'a, T>> {
-        match self.borrow.get() {
-            UNUSED => {
-                self.borrow.set(WRITING);
-                Some(RefMut { _parent: self })
-            },
-            _ => None
+        match BorrowRefMut::new(&self.borrow) {
+            Some(b) => Some(RefMut { _value: unsafe { &mut *self.value.get() }, _borrow: b }),
+            None => None,
         }
     }
 
@@ -368,29 +362,56 @@ impl<T: PartialEq> PartialEq for RefCell<T> {
     }
 }
 
-/// Wraps a borrowed reference to a value in a `RefCell` box.
-#[unstable]
-pub struct Ref<'b, T:'b> {
-    // FIXME #12808: strange name to try to avoid interfering with
-    // field accesses of the contained type via Deref
-    _parent: &'b RefCell<T>
+struct BorrowRef<'b> {
+    _borrow: &'b Cell<BorrowFlag>,
+}
+
+impl<'b> BorrowRef<'b> {
+    fn new(borrow: &'b Cell<BorrowFlag>) -> Option<BorrowRef<'b>> {
+        match borrow.get() {
+            WRITING => None,
+            b => {
+                borrow.set(b + 1);
+                Some(BorrowRef { _borrow: borrow })
+            },
+        }
+    }
 }
 
 #[unsafe_destructor]
-#[unstable]
-impl<'b, T> Drop for Ref<'b, T> {
+impl<'b> Drop for BorrowRef<'b> {
     fn drop(&mut self) {
-        let borrow = self._parent.borrow.get();
+        let borrow = self._borrow.get();
         debug_assert!(borrow != WRITING && borrow != UNUSED);
-        self._parent.borrow.set(borrow - 1);
+        self._borrow.set(borrow - 1);
     }
 }
 
+impl<'b> Clone for BorrowRef<'b> {
+    fn clone(&self) -> BorrowRef<'b> {
+        // Since this Ref exists, we know the borrow flag
+        // is not set to WRITING.
+        let borrow = self._borrow.get();
+        debug_assert!(borrow != WRITING && borrow != UNUSED);
+        self._borrow.set(borrow + 1);
+        BorrowRef { _borrow: self._borrow }
+    }
+}
+
+/// Wraps a borrowed reference to a value in a `RefCell` box.
+#[unstable]
+pub struct Ref<'b, T:'b> {
+    // FIXME #12808: strange name to try to avoid interfering with
+    // field accesses of the contained type via Deref
+    _value: &'b T,
+    _borrow: BorrowRef<'b>,
+}
+
 #[unstable = "waiting for `Deref` to become stable"]
 impl<'b, T> Deref<T> for Ref<'b, T> {
     #[inline]
     fn deref<'a>(&'a self) -> &'a T {
-        unsafe { &*self._parent.value.get() }
+        self._value
     }
 }
 
@@ -401,41 +422,52 @@ impl<'b, T> Deref<T> for Ref<'b, T> {
 /// A `Clone` implementation would interfere with the widespread
 /// use of `r.borrow().clone()` to clone the contents of a `RefCell`.
 #[experimental = "likely to be moved to a method, pending language changes"]
-pub fn clone_ref<'b, T>(orig: &Ref<'b, T>) -> Ref<'b, T> {
-    // Since this Ref exists, we know the borrow flag
-    // is not set to WRITING.
-    let borrow = orig._parent.borrow.get();
-    debug_assert!(borrow != WRITING && borrow != UNUSED);
-    orig._parent.borrow.set(borrow + 1);
-
+pub fn clone_ref<'b, T:Clone>(orig: &Ref<'b, T>) -> Ref<'b, T> {
     Ref {
-        _parent: orig._parent,
+        _value: orig._value,
+        _borrow: orig._borrow.clone(),
     }
 }
 
-/// Wraps a mutable borrowed reference to a value in a `RefCell` box.
-#[unstable]
-pub struct RefMut<'b, T:'b> {
-    // FIXME #12808: strange name to try to avoid interfering with
-    // field accesses of the contained type via Deref
-    _parent: &'b RefCell<T>
+struct BorrowRefMut<'b> {
+    _borrow: &'b Cell<BorrowFlag>,
 }
 
 #[unsafe_destructor]
-#[unstable]
-impl<'b, T> Drop for RefMut<'b, T> {
+impl<'b> Drop for BorrowRefMut<'b> {
     fn drop(&mut self) {
-        let borrow = self._parent.borrow.get();
+        let borrow = self._borrow.get();
         debug_assert!(borrow == WRITING);
-        self._parent.borrow.set(UNUSED);
+        self._borrow.set(UNUSED);
     }
 }
 
+impl<'b> BorrowRefMut<'b> {
+    fn new(borrow: &'b Cell<BorrowFlag>) -> Option<BorrowRefMut<'b>> {
+        match borrow.get() {
+            UNUSED => {
+                borrow.set(WRITING);
+                Some(BorrowRefMut { _borrow: borrow })
+            },
+            _ => None,
+        }
+    }
+}
+
+/// Wraps a mutable borrowed reference to a value in a `RefCell` box.
+#[unstable]
+pub struct RefMut<'b, T:'b> {
+    // FIXME #12808: strange name to try to avoid interfering with
+    // field accesses of the contained type via Deref
+    _value: &'b mut T,
+    _borrow: BorrowRefMut<'b>,
+}
+
 #[unstable = "waiting for `Deref` to become stable"]
 impl<'b, T> Deref<T> for RefMut<'b, T> {
     #[inline]
     fn deref<'a>(&'a self) -> &'a T {
-        unsafe { &*self._parent.value.get() }
+        self._value
     }
 }
 
@@ -443,7 +475,7 @@ impl<'b, T> Deref<T> for RefMut<'b, T> {
 impl<'b, T> DerefMut<T> for RefMut<'b, T> {
     #[inline]
     fn deref_mut<'a>(&'a mut self) -> &'a mut T {
-        unsafe { &mut *self._parent.value.get() }
+        self._value
     }
 }