use std::cell::Cell;
use std::cmp::Ordering;
use std::fmt;
use std::hash::{Hasher, Hash};
use std::mem::{self, forget};
use std::ops::Deref;
use std::ptr;
struct RcBox<T> {
strong: Cell<usize>,
weak: Cell<usize>,
value: T,
}
unsafe fn deallocate<T>(ptr: *mut T, count: usize) {
mem::drop(Vec::from_raw_parts(ptr, 0, count))
}
pub struct Rc<T> {
_ptr: *mut RcBox<T>,
}
impl<T> Rc<T> {
pub fn new(value: T) -> Rc<T> {
let mut rc_box = Box::new(RcBox {
strong: Cell::new(1),
weak: Cell::new(1),
value: value
});
let rc = Rc {
_ptr: &mut *rc_box,
};
mem::forget(rc_box);
rc
}
#[inline]
pub fn try_unwrap(rc: Rc<T>) -> Result<T, Rc<T>> {
if Rc::is_unique(&rc) {
unsafe {
let val = ptr::read(&*rc); deallocate(rc._ptr, 1);
forget(rc);
Ok(val)
}
} else {
Err(rc)
}
}
}
impl<T> Rc<T> {
pub fn downgrade(&self) -> Weak<T> {
self.inc_weak();
Weak { _ptr: self._ptr }
}
#[inline]
pub fn weak_count(this: &Rc<T>) -> usize { this.weak() - 1 }
#[inline]
pub fn strong_count(this: &Rc<T>) -> usize { this.strong() }
#[inline]
pub fn is_unique(rc: &Rc<T>) -> bool {
Rc::weak_count(rc) == 0 && Rc::strong_count(rc) == 1
}
#[inline]
pub fn get_mut(rc: &mut Rc<T>) -> Option<&mut T> {
if Rc::is_unique(rc) {
let inner = unsafe { &mut *rc._ptr };
Some(&mut inner.value)
} else {
None
}
}
}
#[inline]
pub fn weak_count<T>(this: &Rc<T>) -> usize { Rc::weak_count(this) }
#[inline]
pub fn strong_count<T>(this: &Rc<T>) -> usize { Rc::strong_count(this) }
#[inline]
pub fn is_unique<T>(rc: &Rc<T>) -> bool { Rc::is_unique(rc) }
#[inline]
pub fn try_unwrap<T>(rc: Rc<T>) -> Result<T, Rc<T>> { Rc::try_unwrap(rc) }
#[inline]
pub fn get_mut<T>(rc: &mut Rc<T>) -> Option<&mut T> { Rc::get_mut(rc) }
impl<T: Clone> Rc<T> {
#[inline]
pub fn make_unique(&mut self) -> &mut T {
if !Rc::is_unique(self) {
*self = Rc::new((**self).clone())
}
let inner = unsafe { &mut *self._ptr };
&mut inner.value
}
}
impl<T> Deref for Rc<T> {
type Target = T;
#[inline(always)]
fn deref(&self) -> &T {
&self.inner().value
}
}
impl<T> Drop for Rc<T> {
fn drop(&mut self) {
unsafe {
let ptr = self._ptr;
if !(*(&ptr as *const _ as *const *const ())).is_null() {
self.dec_strong();
if self.strong() == 0 {
mem::drop(ptr::read(&(*ptr).value));
self.dec_weak();
if self.weak() == 0 {
deallocate(ptr, 1)
}
}
}
}
}
}
impl<T> Clone for Rc<T> {
#[inline]
fn clone(&self) -> Rc<T> {
self.inc_strong();
Rc { _ptr: self._ptr }
}
}
impl<T: Default> Default for Rc<T> {
#[inline]
fn default() -> Rc<T> {
Rc::new(Default::default())
}
}
impl<T: PartialEq> PartialEq for Rc<T> {
#[inline(always)]
fn eq(&self, other: &Rc<T>) -> bool { **self == **other }
#[inline(always)]
fn ne(&self, other: &Rc<T>) -> bool { **self != **other }
}
impl<T: Eq> Eq for Rc<T> {}
impl<T: PartialOrd> PartialOrd for Rc<T> {
#[inline(always)]
fn partial_cmp(&self, other: &Rc<T>) -> Option<Ordering> {
(**self).partial_cmp(&**other)
}
#[inline(always)]
fn lt(&self, other: &Rc<T>) -> bool { **self < **other }
#[inline(always)]
fn le(&self, other: &Rc<T>) -> bool { **self <= **other }
#[inline(always)]
fn gt(&self, other: &Rc<T>) -> bool { **self > **other }
#[inline(always)]
fn ge(&self, other: &Rc<T>) -> bool { **self >= **other }
}
impl<T: Ord> Ord for Rc<T> {
#[inline]
fn cmp(&self, other: &Rc<T>) -> Ordering { (**self).cmp(&**other) }
}
impl<T: Hash> Hash for Rc<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
(**self).hash(state);
}
}
impl<T: fmt::Display> fmt::Display for Rc<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&**self, f)
}
}
impl<T: fmt::Debug> fmt::Debug for Rc<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(&**self, f)
}
}
impl<T> fmt::Pointer for Rc<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Pointer::fmt(&self._ptr, f)
}
}
pub struct Weak<T> {
_ptr: *mut RcBox<T>,
}
impl<T> Weak<T> {
pub fn upgrade(&self) -> Option<Rc<T>> {
if self.strong() == 0 {
None
} else {
self.inc_strong();
Some(Rc { _ptr: self._ptr })
}
}
}
impl<T> Drop for Weak<T> {
fn drop(&mut self) {
unsafe {
let ptr = self._ptr;
if !(*(&ptr as *const _ as *const *const ())).is_null() {
self.dec_weak();
if self.weak() == 0 {
deallocate(ptr, 1)
}
}
}
}
}
impl<T> Clone for Weak<T> {
#[inline]
fn clone(&self) -> Weak<T> {
self.inc_weak();
Weak { _ptr: self._ptr }
}
}
impl<T: fmt::Debug> fmt::Debug for Weak<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "(Weak)")
}
}
#[doc(hidden)]
trait RcBoxPtr<T> {
fn inner(&self) -> &RcBox<T>;
#[inline]
fn strong(&self) -> usize { 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) -> usize { 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<T> RcBoxPtr<T> for Rc<T> {
#[inline(always)]
fn inner(&self) -> &RcBox<T> {
unsafe {
&*self._ptr
}
}
}
impl<T> RcBoxPtr<T> for Weak<T> {
#[inline(always)]
fn inner(&self) -> &RcBox<T> {
unsafe {
&*self._ptr
}
}
}
#[cfg(test)]
mod tests {
use super::{Rc, Weak, weak_count, strong_count};
use std::cell::RefCell;
use std::mem::drop;
#[test]
fn test_clone() {
let x = Rc::new(RefCell::new(5));
let y = x.clone();
*x.borrow_mut() = 20;
assert_eq!(*y.borrow(), 20);
}
#[test]
fn test_simple() {
let x = Rc::new(5);
assert_eq!(*x, 5);
}
#[test]
fn test_simple_clone() {
let x = Rc::new(5);
let y = x.clone();
assert_eq!(*x, 5);
assert_eq!(*y, 5);
}
#[test]
fn test_destructor() {
let x: Rc<Box<_>> = Rc::new(Box::new(5));
assert_eq!(**x, 5);
}
#[test]
fn test_live() {
let x = Rc::new(5);
let y = x.downgrade();
assert!(y.upgrade().is_some());
}
#[test]
fn test_dead() {
let x = Rc::new(5);
let y = x.downgrade();
drop(x);
assert!(y.upgrade().is_none());
}
#[test]
fn weak_self_cyclic() {
struct Cycle {
x: RefCell<Option<Weak<Cycle>>>
}
let a = Rc::new(Cycle { x: RefCell::new(None) });
let b = a.clone().downgrade();
*a.x.borrow_mut() = Some(b);
}
#[test]
fn is_unique() {
let x = Rc::new(3);
assert!(super::is_unique(&x));
let y = x.clone();
assert!(!super::is_unique(&x));
drop(y);
assert!(super::is_unique(&x));
let w = x.downgrade();
assert!(!super::is_unique(&x));
drop(w);
assert!(super::is_unique(&x));
}
#[test]
fn test_strong_count() {
let a = Rc::new(0u32);
assert!(strong_count(&a) == 1);
let w = a.downgrade();
assert!(strong_count(&a) == 1);
let b = w.upgrade().expect("upgrade of live rc failed");
assert!(strong_count(&b) == 2);
assert!(strong_count(&a) == 2);
drop(w);
drop(a);
assert!(strong_count(&b) == 1);
let c = b.clone();
assert!(strong_count(&b) == 2);
assert!(strong_count(&c) == 2);
}
#[test]
fn test_weak_count() {
let a = Rc::new(0u32);
assert!(strong_count(&a) == 1);
assert!(weak_count(&a) == 0);
let w = a.downgrade();
assert!(strong_count(&a) == 1);
assert!(weak_count(&a) == 1);
drop(w);
assert!(strong_count(&a) == 1);
assert!(weak_count(&a) == 0);
let c = a.clone();
assert!(strong_count(&a) == 2);
assert!(weak_count(&a) == 0);
drop(c);
}
#[test]
fn try_unwrap() {
let x = Rc::new(3);
assert_eq!(super::try_unwrap(x), Ok(3));
let x = Rc::new(4);
let _y = x.clone();
assert_eq!(super::try_unwrap(x), Err(Rc::new(4)));
let x = Rc::new(5);
let _w = x.downgrade();
assert_eq!(super::try_unwrap(x), Err(Rc::new(5)));
}
#[test]
fn get_mut() {
let mut x = Rc::new(3);
*super::get_mut(&mut x).unwrap() = 4;
assert_eq!(*x, 4);
let y = x.clone();
assert!(super::get_mut(&mut x).is_none());
drop(y);
assert!(super::get_mut(&mut x).is_some());
let _w = x.downgrade();
assert!(super::get_mut(&mut x).is_none());
}
#[test]
fn test_cowrc_clone_make_unique() {
let mut cow0 = Rc::new(75);
let mut cow1 = cow0.clone();
let mut cow2 = cow1.clone();
assert!(75 == *cow0.make_unique());
assert!(75 == *cow1.make_unique());
assert!(75 == *cow2.make_unique());
*cow0.make_unique() += 1;
*cow1.make_unique() += 2;
*cow2.make_unique() += 3;
assert!(76 == *cow0);
assert!(77 == *cow1);
assert!(78 == *cow2);
assert!(*cow0 != *cow1);
assert!(*cow0 != *cow2);
assert!(*cow1 != *cow2);
}
#[test]
fn test_cowrc_clone_unique2() {
let mut cow0 = Rc::new(75);
let cow1 = cow0.clone();
let cow2 = cow1.clone();
assert!(75 == *cow0);
assert!(75 == *cow1);
assert!(75 == *cow2);
*cow0.make_unique() += 1;
assert!(76 == *cow0);
assert!(75 == *cow1);
assert!(75 == *cow2);
assert!(*cow0 != *cow1);
assert!(*cow0 != *cow2);
assert!(*cow1 == *cow2);
}
#[test]
fn test_cowrc_clone_weak() {
let mut cow0 = Rc::new(75);
let cow1_weak = cow0.downgrade();
assert!(75 == *cow0);
assert!(75 == *cow1_weak.upgrade().unwrap());
*cow0.make_unique() += 1;
assert!(76 == *cow0);
assert!(cow1_weak.upgrade().is_none());
}
#[test]
fn test_show() {
let foo = Rc::new(75);
assert_eq!(format!("{:?}", foo), "75");
}
}