rc: Use ~T for allocation

Simplify Rc<T>/RcMut<T> by using ~T when allocating a reference counted
box.
This commit is contained in:
blake2-ppc
2013-07-24 14:11:49 +02:00
committed by Daniel Micay
parent 4a2d22bdb1
commit 8f86fa3b31
2 changed files with 44 additions and 48 deletions

View File

@@ -23,11 +23,17 @@ cycle cannot be created with `Rc<T>` because there is no way to modify it after
use std::cast;
use std::libc::{c_void, size_t, malloc, free};
use std::ptr;
use std::sys;
use std::unstable::intrinsics;
// Convert ~T into *mut T without dropping it
#[inline]
unsafe fn owned_to_raw<T>(mut box: ~T) -> *mut T {
let ptr = ptr::to_mut_unsafe_ptr(box);
intrinsics::forget(box);
ptr
}
struct RcBox<T> {
value: T,
count: uint
@@ -42,21 +48,20 @@ pub struct Rc<T> {
impl<T> Rc<T> {
unsafe fn new(value: T) -> Rc<T> {
let ptr = malloc(sys::size_of::<RcBox<T>>() as size_t) as *mut RcBox<T>;
assert!(!ptr::is_null(ptr));
intrinsics::move_val_init(&mut *ptr, RcBox{value: value, count: 1});
Rc{ptr: ptr}
Rc{ptr: owned_to_raw(~RcBox{value: value, count: 1})}
}
}
// FIXME: #6516: should be a static method
pub fn rc_from_owned<T: Send>(value: T) -> Rc<T> {
unsafe { Rc::new(value) }
impl<T: Send> Rc<T> {
pub fn from_owned(value: T) -> Rc<T> {
unsafe { Rc::new(value) }
}
}
// FIXME: #6516: should be a static method
pub fn rc_from_const<T: Freeze>(value: T) -> Rc<T> {
unsafe { Rc::new(value) }
impl<T: Freeze> Rc<T> {
pub fn from_const(value: T) -> Rc<T> {
unsafe { Rc::new(value) }
}
}
impl<T> Rc<T> {
@@ -73,8 +78,7 @@ impl<T> Drop for Rc<T> {
if self.ptr.is_not_null() {
(*self.ptr).count -= 1;
if (*self.ptr).count == 0 {
ptr::read_ptr(self.ptr);
free(self.ptr as *c_void)
let _: ~T = cast::transmute(self.ptr);
}
}
}
@@ -107,7 +111,7 @@ mod test_rc {
#[test]
fn test_clone() {
let x = rc_from_owned(Cell::new(5));
let x = Rc::from_owned(Cell::new(5));
let y = x.clone();
do x.borrow().with_mut_ref |inner| {
*inner = 20;
@@ -117,7 +121,7 @@ mod test_rc {
#[test]
fn test_deep_clone() {
let x = rc_from_owned(Cell::new(5));
let x = Rc::from_owned(Cell::new(5));
let y = x.deep_clone();
do x.borrow().with_mut_ref |inner| {
*inner = 20;
@@ -127,13 +131,13 @@ mod test_rc {
#[test]
fn test_simple() {
let x = rc_from_const(5);
let x = Rc::from_const(5);
assert_eq!(*x.borrow(), 5);
}
#[test]
fn test_simple_clone() {
let x = rc_from_const(5);
let x = Rc::from_const(5);
let y = x.clone();
assert_eq!(*x.borrow(), 5);
assert_eq!(*y.borrow(), 5);
@@ -141,17 +145,11 @@ mod test_rc {
#[test]
fn test_destructor() {
let x = rc_from_owned(~5);
let x = Rc::from_owned(~5);
assert_eq!(**x.borrow(), 5);
}
}
#[abi = "rust-intrinsic"]
extern "rust-intrinsic" {
fn init<T>() -> T;
fn uninit<T>() -> T;
}
#[deriving(Eq)]
enum Borrow {
Mutable,
@@ -175,21 +173,20 @@ pub struct RcMut<T> {
impl<T> RcMut<T> {
unsafe fn new(value: T) -> RcMut<T> {
let ptr = malloc(sys::size_of::<RcMutBox<T>>() as size_t) as *mut RcMutBox<T>;
assert!(!ptr::is_null(ptr));
intrinsics::move_val_init(&mut *ptr, RcMutBox{value: value, count: 1, borrow: Nothing});
RcMut{ptr: ptr}
RcMut{ptr: owned_to_raw(~RcMutBox{value: value, count: 1, borrow: Nothing})}
}
}
// FIXME: #6516: should be a static method
pub fn rc_mut_from_owned<T: Send>(value: T) -> RcMut<T> {
unsafe { RcMut::new(value) }
impl<T: Send> RcMut<T> {
pub fn from_owned(value: T) -> RcMut<T> {
unsafe { RcMut::new(value) }
}
}
// FIXME: #6516: should be a static method
pub fn rc_mut_from_const<T: Freeze>(value: T) -> RcMut<T> {
unsafe { RcMut::new(value) }
impl<T: Freeze> RcMut<T> {
pub fn from_const(value: T) -> RcMut<T> {
unsafe { RcMut::new(value) }
}
}
impl<T> RcMut<T> {
@@ -226,8 +223,7 @@ impl<T> Drop for RcMut<T> {
if self.ptr.is_not_null() {
(*self.ptr).count -= 1;
if (*self.ptr).count == 0 {
ptr::replace_ptr(self.ptr, uninit());
free(self.ptr as *c_void)
let _: ~T = cast::transmute(self.ptr);
}
}
}
@@ -262,7 +258,7 @@ mod test_rc_mut {
#[test]
fn test_clone() {
let x = rc_mut_from_owned(5);
let x = RcMut::from_owned(5);
let y = x.clone();
do x.with_mut_borrow |value| {
*value = 20;
@@ -274,7 +270,7 @@ mod test_rc_mut {
#[test]
fn test_deep_clone() {
let x = rc_mut_from_const(5);
let x = RcMut::from_const(5);
let y = x.deep_clone();
do x.with_mut_borrow |value| {
*value = 20;
@@ -286,7 +282,7 @@ mod test_rc_mut {
#[test]
fn borrow_many() {
let x = rc_mut_from_owned(5);
let x = RcMut::from_owned(5);
let y = x.clone();
do x.with_borrow |a| {
@@ -302,7 +298,7 @@ mod test_rc_mut {
#[test]
fn modify() {
let x = rc_mut_from_const(5);
let x = RcMut::from_const(5);
let y = x.clone();
do y.with_mut_borrow |a| {
@@ -317,14 +313,14 @@ mod test_rc_mut {
#[test]
fn release_immutable() {
let x = rc_mut_from_owned(5);
let x = RcMut::from_owned(5);
do x.with_borrow |_| {}
do x.with_mut_borrow |_| {}
}
#[test]
fn release_mutable() {
let x = rc_mut_from_const(5);
let x = RcMut::from_const(5);
do x.with_mut_borrow |_| {}
do x.with_borrow |_| {}
}
@@ -332,7 +328,7 @@ mod test_rc_mut {
#[test]
#[should_fail]
fn frozen() {
let x = rc_mut_from_owned(5);
let x = RcMut::from_owned(5);
let y = x.clone();
do x.with_borrow |_| {
@@ -344,7 +340,7 @@ mod test_rc_mut {
#[test]
#[should_fail]
fn mutable_dupe() {
let x = rc_mut_from_const(5);
let x = RcMut::from_const(5);
let y = x.clone();
do x.with_mut_borrow |_| {
@@ -356,7 +352,7 @@ mod test_rc_mut {
#[test]
#[should_fail]
fn mutable_freeze() {
let x = rc_mut_from_owned(5);
let x = RcMut::from_owned(5);
let y = x.clone();
do x.with_mut_borrow |_| {
@@ -368,7 +364,7 @@ mod test_rc_mut {
#[test]
#[should_fail]
fn restore_freeze() {
let x = rc_mut_from_const(5);
let x = RcMut::from_const(5);
let y = x.clone();
do x.with_borrow |_| {

View File

@@ -14,7 +14,7 @@ fn o<T: Send>(_: &T) {}
fn c<T: Freeze>(_: &T) {}
fn main() {
let x = extra::rc::rc_mut_from_owned(0);
let x = extra::rc::RcMut::from_owned(0);
o(&x); //~ ERROR instantiating a type parameter with an incompatible type `extra::rc::RcMut<int>`, which does not fulfill `Send`
c(&x); //~ ERROR instantiating a type parameter with an incompatible type `extra::rc::RcMut<int>`, which does not fulfill `Freeze`
}