liballoc: Use NonZero in Rc.

This commit is contained in:
Luqman Aden 2014-12-04 12:59:28 -05:00
parent bb44737748
commit 0d48f76224

View File

@ -153,8 +153,7 @@ use core::mem::{transmute, min_align_of, size_of, forget};
use core::ops::{Deref, Drop};
use core::option::Option;
use core::option::Option::{Some, None};
use core::ptr;
use core::ptr::RawPtr;
use core::ptr::{mod, NonZero, RawPtr};
use core::result::Result;
use core::result::Result::{Ok, Err};
@ -174,7 +173,7 @@ struct RcBox<T> {
pub struct Rc<T> {
// FIXME #12808: strange names to try to avoid interfering with field accesses of the contained
// type via Deref
_ptr: *mut RcBox<T>,
_ptr: NonZero<*mut RcBox<T>>,
_nosend: marker::NoSend,
_noshare: marker::NoSync
}
@ -196,11 +195,11 @@ impl<T> Rc<T> {
// there is an implicit weak pointer owned by all the strong pointers, which
// ensures that the weak destructor never frees the allocation while the strong
// destructor is running, even if the weak pointer is stored inside the strong one.
_ptr: transmute(box RcBox {
_ptr: NonZero(transmute(box RcBox {
value: value,
strong: Cell::new(1),
weak: Cell::new(1)
}),
})),
_nosend: marker::NoSend,
_noshare: marker::NoSync
}
@ -281,7 +280,8 @@ pub fn try_unwrap<T>(rc: Rc<T>) -> Result<T, Rc<T>> {
let val = ptr::read(&*rc); // copy the contained object
// destruct the box and skip our Drop
// we can ignore the refcounts because we know we're unique
deallocate(rc._ptr as *mut u8, size_of::<RcBox<T>>(),
let NonZero(ptr) = rc._ptr;
deallocate(ptr as *mut u8, size_of::<RcBox<T>>(),
min_align_of::<RcBox<T>>());
forget(rc);
Ok(val)
@ -311,7 +311,10 @@ pub fn try_unwrap<T>(rc: Rc<T>) -> Result<T, Rc<T>> {
#[experimental]
pub fn get_mut<'a, T>(rc: &'a mut Rc<T>) -> Option<&'a mut T> {
if is_unique(rc) {
let inner = unsafe { &mut *rc._ptr };
let inner = unsafe {
let NonZero(ptr) = rc._ptr;
&mut *ptr
};
Some(&mut inner.value)
} else {
None
@ -343,7 +346,10 @@ impl<T: Clone> Rc<T> {
// pointer that will ever be returned to T. Our reference count is guaranteed to be 1 at
// this point, and we required the `Rc<T>` itself to be `mut`, so we're returning the only
// possible reference to the inner value.
let inner = unsafe { &mut *self._ptr };
let inner = unsafe {
let NonZero(ptr) = self._ptr;
&mut *ptr
};
&mut inner.value
}
}
@ -391,7 +397,8 @@ impl<T> Drop for Rc<T> {
/// ```
fn drop(&mut self) {
unsafe {
if !self._ptr.is_null() {
let NonZero(ptr) = self._ptr;
if !ptr.is_null() {
self.dec_strong();
if self.strong() == 0 {
ptr::read(&**self); // destroy the contained object
@ -401,7 +408,7 @@ impl<T> Drop for Rc<T> {
self.dec_weak();
if self.weak() == 0 {
deallocate(self._ptr as *mut u8, size_of::<RcBox<T>>(),
deallocate(ptr as *mut u8, size_of::<RcBox<T>>(),
min_align_of::<RcBox<T>>())
}
}
@ -618,7 +625,7 @@ impl<T: fmt::Show> fmt::Show for Rc<T> {
pub struct Weak<T> {
// FIXME #12808: strange names to try to avoid interfering with
// field accesses of the contained type via Deref
_ptr: *mut RcBox<T>,
_ptr: NonZero<*mut RcBox<T>>,
_nosend: marker::NoSend,
_noshare: marker::NoSync
}
@ -682,12 +689,13 @@ impl<T> Drop for Weak<T> {
/// ```
fn drop(&mut self) {
unsafe {
if !self._ptr.is_null() {
let NonZero(ptr) = self._ptr;
if !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.weak() == 0 {
deallocate(self._ptr as *mut u8, size_of::<RcBox<T>>(),
deallocate(ptr as *mut u8, size_of::<RcBox<T>>(),
min_align_of::<RcBox<T>>())
}
}
@ -742,12 +750,18 @@ trait RcBoxPtr<T> {
impl<T> RcBoxPtr<T> for Rc<T> {
#[inline(always)]
fn inner(&self) -> &RcBox<T> { unsafe { &(*self._ptr) } }
fn inner(&self) -> &RcBox<T> {
let NonZero(ptr) = self._ptr;
unsafe { &(*ptr) }
}
}
impl<T> RcBoxPtr<T> for Weak<T> {
#[inline(always)]
fn inner(&self) -> &RcBox<T> { unsafe { &(*self._ptr) } }
fn inner(&self) -> &RcBox<T> {
let NonZero(ptr) = self._ptr;
unsafe { &(*ptr) }
}
}
#[cfg(test)]