Simplify RefCell code a bit, make deref a no-op.

This commit is contained in:
Tobias Bucher 2014-11-29 01:20:14 +01:00
parent fb52e69a50
commit 5048953deb

View file

@ -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> {
}
}
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]
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<T>
}
#[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<T> 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<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(),
}
}
struct BorrowRefMut<'b> {
_borrow: &'b Cell<BorrowFlag>,
}
#[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<BorrowFlag>) -> Option<BorrowRefMut<'b>> {
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<T>
}
#[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<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
}
}