From 5048953debe9eb44c672f3c453e894bd64a1301a Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Sat, 29 Nov 2014 01:20:14 +0100 Subject: [PATCH] Simplify `RefCell` code a bit, make `deref` a no-op. --- src/libcore/cell.rs | 122 ++++++++++++++++++++++++++++---------------- 1 file changed, 77 insertions(+), 45 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 RefCell { /// 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> { - 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 RefCell { /// 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> { - 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 PartialEq for RefCell { } } +struct BorrowRef<'b> { + _borrow: &'b Cell, +} + +impl<'b> BorrowRef<'b> { + fn new(borrow: &'b Cell) -> Option> { + match borrow.get() { + WRITING => None, + b => { + borrow.set(b + 1); + Some(BorrowRef { _borrow: borrow }) + }, + } + } +} + +#[unsafe_destructor] +impl<'b> Drop for BorrowRef<'b> { + fn drop(&mut self) { + let borrow = self._borrow.get(); + debug_assert!(borrow != WRITING && borrow != UNUSED); + 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 - _parent: &'b RefCell -} - -#[unsafe_destructor] -#[unstable] -impl<'b, T> Drop for Ref<'b, T> { - fn drop(&mut self) { - let borrow = self._parent.borrow.get(); - debug_assert!(borrow != WRITING && borrow != UNUSED); - self._parent.borrow.set(borrow - 1); - } + _value: &'b T, + _borrow: BorrowRef<'b>, } #[unstable = "waiting for `Deref` to become stable"] impl<'b, T> Deref for Ref<'b, T> { #[inline] fn deref<'a>(&'a self) -> &'a T { - unsafe { &*self._parent.value.get() } + self._value } } @@ -401,15 +422,35 @@ impl<'b, T> Deref 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(), + } +} + +struct BorrowRefMut<'b> { + _borrow: &'b Cell, +} + +#[unsafe_destructor] +impl<'b> Drop for BorrowRefMut<'b> { + fn drop(&mut self) { + let borrow = self._borrow.get(); + debug_assert!(borrow == WRITING); + self._borrow.set(UNUSED); + } +} + +impl<'b> BorrowRefMut<'b> { + fn new(borrow: &'b Cell) -> Option> { + match borrow.get() { + UNUSED => { + borrow.set(WRITING); + Some(BorrowRefMut { _borrow: borrow }) + }, + _ => None, + } } } @@ -418,24 +459,15 @@ pub fn clone_ref<'b, T>(orig: &Ref<'b, T>) -> Ref<'b, T> { 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 -} - -#[unsafe_destructor] -#[unstable] -impl<'b, T> Drop for RefMut<'b, T> { - fn drop(&mut self) { - let borrow = self._parent.borrow.get(); - debug_assert!(borrow == WRITING); - self._parent.borrow.set(UNUSED); - } + _value: &'b mut T, + _borrow: BorrowRefMut<'b>, } #[unstable = "waiting for `Deref` to become stable"] impl<'b, T> Deref 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 for RefMut<'b, T> { impl<'b, T> DerefMut for RefMut<'b, T> { #[inline] fn deref_mut<'a>(&'a mut self) -> &'a mut T { - unsafe { &mut *self._parent.value.get() } + self._value } }