From db5206c32a879d5058d6a5cdce39c13c763fbdd5 Mon Sep 17 00:00:00 2001 From: Edward Wang Date: Fri, 21 Mar 2014 15:16:07 +0800 Subject: [PATCH] Rewrite rc::Rc using cell::Cell Since `Arc` has been using `Atomic`, this closes 12625. Closes #12625. --- src/libstd/rc.rs | 99 +++++++++++++++++++++++++++++--------------- src/libsyntax/ast.rs | 8 ---- 2 files changed, 65 insertions(+), 42 deletions(-) diff --git a/src/libstd/rc.rs b/src/libstd/rc.rs index 605cbd3f28a..dcf4d31c308 100644 --- a/src/libstd/rc.rs +++ b/src/libstd/rc.rs @@ -24,18 +24,20 @@ pointers, and then storing the parent pointers as `Weak` pointers. */ use cast::transmute; +use cell::Cell; use clone::Clone; use cmp::{Eq, Ord}; use kinds::marker; use ops::{Deref, Drop}; use option::{Option, Some, None}; use ptr; +use ptr::RawPtr; use rt::global_heap::exchange_free; struct RcBox { value: T, - strong: uint, - weak: uint + strong: Cell, + weak: Cell } /// Immutable reference counted pointer type @@ -56,7 +58,11 @@ impl Rc { // destructor never frees the allocation while the // strong destructor is running, even if the weak // pointer is stored inside the strong one. - ptr: transmute(~RcBox { value: value, strong: 1, weak: 1 }), + ptr: transmute(~RcBox { + value: value, + strong: Cell::new(1), + weak: Cell::new(1) + }), nosend: marker::NoSend, noshare: marker::NoShare } @@ -67,13 +73,11 @@ impl Rc { impl Rc { /// Downgrade the reference-counted pointer to a weak reference pub fn downgrade(&self) -> Weak { - unsafe { - (*self.ptr).weak += 1; - Weak { - ptr: self.ptr, - nosend: marker::NoSend, - noshare: marker::NoShare - } + self.inc_weak(); + Weak { + ptr: self.ptr, + nosend: marker::NoSend, + noshare: marker::NoShare } } } @@ -82,7 +86,7 @@ impl Deref for Rc { /// Borrow the value contained in the reference-counted box #[inline(always)] fn deref<'a>(&'a self) -> &'a T { - unsafe { &(*self.ptr).value } + &self.inner().value } } @@ -90,16 +94,16 @@ impl Deref for Rc { impl Drop for Rc { fn drop(&mut self) { unsafe { - if self.ptr != 0 as *mut RcBox { - (*self.ptr).strong -= 1; - if (*self.ptr).strong == 0 { + if !self.ptr.is_null() { + self.dec_strong(); + if self.strong() == 0 { ptr::read(self.deref()); // destroy the contained object // remove the implicit "strong weak" pointer now // that we've destroyed the contents. - (*self.ptr).weak -= 1; + self.dec_weak(); - if (*self.ptr).weak == 0 { + if self.weak() == 0 { exchange_free(self.ptr as *u8) } } @@ -111,10 +115,8 @@ impl Drop for Rc { impl Clone for Rc { #[inline] fn clone(&self) -> Rc { - unsafe { - (*self.ptr).strong += 1; - Rc { ptr: self.ptr, nosend: marker::NoSend, noshare: marker::NoShare } - } + self.inc_strong(); + Rc { ptr: self.ptr, nosend: marker::NoSend, noshare: marker::NoShare } } } @@ -151,13 +153,11 @@ pub struct Weak { impl Weak { /// Upgrade a weak reference to a strong reference pub fn upgrade(&self) -> Option> { - unsafe { - if (*self.ptr).strong == 0 { - None - } else { - (*self.ptr).strong += 1; - Some(Rc { ptr: self.ptr, nosend: marker::NoSend, noshare: marker::NoShare }) - } + if self.strong() == 0 { + None + } else { + self.inc_strong(); + Some(Rc { ptr: self.ptr, nosend: marker::NoSend, noshare: marker::NoShare }) } } } @@ -166,11 +166,11 @@ impl Weak { impl Drop for Weak { fn drop(&mut self) { unsafe { - if self.ptr != 0 as *mut RcBox { - (*self.ptr).weak -= 1; + if !self.ptr.is_null() { + self.dec_weak(); // the weak count starts at 1, and will only go to // zero if all the strong pointers have disappeared. - if (*self.ptr).weak == 0 { + if self.weak() == 0 { exchange_free(self.ptr as *u8) } } @@ -181,13 +181,44 @@ impl Drop for Weak { impl Clone for Weak { #[inline] fn clone(&self) -> Weak { - unsafe { - (*self.ptr).weak += 1; - Weak { ptr: self.ptr, nosend: marker::NoSend, noshare: marker::NoShare } - } + self.inc_weak(); + Weak { ptr: self.ptr, nosend: marker::NoSend, noshare: marker::NoShare } } } +#[allow(missing_doc)] +trait RcBoxPtr { + fn inner<'a>(&'a self) -> &'a RcBox; + + #[inline] + fn strong(&self) -> uint { self.inner().strong.get() } + + #[inline] + fn inc_strong(&self) { self.inner().strong.set(self.strong() + 1); } + + #[inline] + fn dec_strong(&self) { self.inner().strong.set(self.strong() - 1); } + + #[inline] + fn weak(&self) -> uint { self.inner().weak.get() } + + #[inline] + fn inc_weak(&self) { self.inner().weak.set(self.weak() + 1); } + + #[inline] + fn dec_weak(&self) { self.inner().weak.set(self.weak() - 1); } +} + +impl RcBoxPtr for Rc { + #[inline(always)] + fn inner<'a>(&'a self) -> &'a RcBox { unsafe { &(*self.ptr) } } +} + +impl RcBoxPtr for Weak { + #[inline(always)] + fn inner<'a>(&'a self) -> &'a RcBox { unsafe { &(*self.ptr) } } +} + #[cfg(test)] mod tests { use prelude::*; diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index d1d9ae2322d..baea0a19f96 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1156,14 +1156,6 @@ mod test { use codemap::*; use super::*; - fn is_freeze() {} - - // Assert that the AST remains Freeze (#10693). - #[test] - fn ast_is_freeze() { - is_freeze::(); - } - // are ASTs encodable? #[test] fn check_asts_encodable() {