mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +00:00
rc: Use ~T for allocation
Simplify Rc<T>/RcMut<T> by using ~T when allocating a reference counted box.
This commit is contained in:
parent
4a2d22bdb1
commit
8f86fa3b31
@ -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::cast;
|
||||||
use std::libc::{c_void, size_t, malloc, free};
|
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::sys;
|
|
||||||
use std::unstable::intrinsics;
|
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> {
|
struct RcBox<T> {
|
||||||
value: T,
|
value: T,
|
||||||
count: uint
|
count: uint
|
||||||
@ -42,22 +48,21 @@ pub struct Rc<T> {
|
|||||||
|
|
||||||
impl<T> Rc<T> {
|
impl<T> Rc<T> {
|
||||||
unsafe fn new(value: 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>;
|
Rc{ptr: owned_to_raw(~RcBox{value: value, count: 1})}
|
||||||
assert!(!ptr::is_null(ptr));
|
|
||||||
intrinsics::move_val_init(&mut *ptr, RcBox{value: value, count: 1});
|
|
||||||
Rc{ptr: ptr}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: #6516: should be a static method
|
impl<T: Send> Rc<T> {
|
||||||
pub fn rc_from_owned<T: Send>(value: T) -> Rc<T> {
|
pub fn from_owned(value: T) -> Rc<T> {
|
||||||
unsafe { Rc::new(value) }
|
unsafe { Rc::new(value) }
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: #6516: should be a static method
|
impl<T: Freeze> Rc<T> {
|
||||||
pub fn rc_from_const<T: Freeze>(value: T) -> Rc<T> {
|
pub fn from_const(value: T) -> Rc<T> {
|
||||||
unsafe { Rc::new(value) }
|
unsafe { Rc::new(value) }
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T> Rc<T> {
|
impl<T> Rc<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -73,8 +78,7 @@ impl<T> Drop for Rc<T> {
|
|||||||
if self.ptr.is_not_null() {
|
if self.ptr.is_not_null() {
|
||||||
(*self.ptr).count -= 1;
|
(*self.ptr).count -= 1;
|
||||||
if (*self.ptr).count == 0 {
|
if (*self.ptr).count == 0 {
|
||||||
ptr::read_ptr(self.ptr);
|
let _: ~T = cast::transmute(self.ptr);
|
||||||
free(self.ptr as *c_void)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -107,7 +111,7 @@ mod test_rc {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_clone() {
|
fn test_clone() {
|
||||||
let x = rc_from_owned(Cell::new(5));
|
let x = Rc::from_owned(Cell::new(5));
|
||||||
let y = x.clone();
|
let y = x.clone();
|
||||||
do x.borrow().with_mut_ref |inner| {
|
do x.borrow().with_mut_ref |inner| {
|
||||||
*inner = 20;
|
*inner = 20;
|
||||||
@ -117,7 +121,7 @@ mod test_rc {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_deep_clone() {
|
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();
|
let y = x.deep_clone();
|
||||||
do x.borrow().with_mut_ref |inner| {
|
do x.borrow().with_mut_ref |inner| {
|
||||||
*inner = 20;
|
*inner = 20;
|
||||||
@ -127,13 +131,13 @@ mod test_rc {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_simple() {
|
fn test_simple() {
|
||||||
let x = rc_from_const(5);
|
let x = Rc::from_const(5);
|
||||||
assert_eq!(*x.borrow(), 5);
|
assert_eq!(*x.borrow(), 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_simple_clone() {
|
fn test_simple_clone() {
|
||||||
let x = rc_from_const(5);
|
let x = Rc::from_const(5);
|
||||||
let y = x.clone();
|
let y = x.clone();
|
||||||
assert_eq!(*x.borrow(), 5);
|
assert_eq!(*x.borrow(), 5);
|
||||||
assert_eq!(*y.borrow(), 5);
|
assert_eq!(*y.borrow(), 5);
|
||||||
@ -141,17 +145,11 @@ mod test_rc {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_destructor() {
|
fn test_destructor() {
|
||||||
let x = rc_from_owned(~5);
|
let x = Rc::from_owned(~5);
|
||||||
assert_eq!(**x.borrow(), 5);
|
assert_eq!(**x.borrow(), 5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[abi = "rust-intrinsic"]
|
|
||||||
extern "rust-intrinsic" {
|
|
||||||
fn init<T>() -> T;
|
|
||||||
fn uninit<T>() -> T;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[deriving(Eq)]
|
#[deriving(Eq)]
|
||||||
enum Borrow {
|
enum Borrow {
|
||||||
Mutable,
|
Mutable,
|
||||||
@ -175,22 +173,21 @@ pub struct RcMut<T> {
|
|||||||
|
|
||||||
impl<T> RcMut<T> {
|
impl<T> RcMut<T> {
|
||||||
unsafe fn new(value: 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>;
|
RcMut{ptr: owned_to_raw(~RcMutBox{value: value, count: 1, borrow: Nothing})}
|
||||||
assert!(!ptr::is_null(ptr));
|
|
||||||
intrinsics::move_val_init(&mut *ptr, RcMutBox{value: value, count: 1, borrow: Nothing});
|
|
||||||
RcMut{ptr: ptr}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: #6516: should be a static method
|
impl<T: Send> RcMut<T> {
|
||||||
pub fn rc_mut_from_owned<T: Send>(value: T) -> RcMut<T> {
|
pub fn from_owned(value: T) -> RcMut<T> {
|
||||||
unsafe { RcMut::new(value) }
|
unsafe { RcMut::new(value) }
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: #6516: should be a static method
|
impl<T: Freeze> RcMut<T> {
|
||||||
pub fn rc_mut_from_const<T: Freeze>(value: T) -> RcMut<T> {
|
pub fn from_const(value: T) -> RcMut<T> {
|
||||||
unsafe { RcMut::new(value) }
|
unsafe { RcMut::new(value) }
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T> RcMut<T> {
|
impl<T> RcMut<T> {
|
||||||
/// Fails if there is already a mutable borrow of the box
|
/// Fails if there is already a mutable borrow of the box
|
||||||
@ -226,8 +223,7 @@ impl<T> Drop for RcMut<T> {
|
|||||||
if self.ptr.is_not_null() {
|
if self.ptr.is_not_null() {
|
||||||
(*self.ptr).count -= 1;
|
(*self.ptr).count -= 1;
|
||||||
if (*self.ptr).count == 0 {
|
if (*self.ptr).count == 0 {
|
||||||
ptr::replace_ptr(self.ptr, uninit());
|
let _: ~T = cast::transmute(self.ptr);
|
||||||
free(self.ptr as *c_void)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -262,7 +258,7 @@ mod test_rc_mut {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_clone() {
|
fn test_clone() {
|
||||||
let x = rc_mut_from_owned(5);
|
let x = RcMut::from_owned(5);
|
||||||
let y = x.clone();
|
let y = x.clone();
|
||||||
do x.with_mut_borrow |value| {
|
do x.with_mut_borrow |value| {
|
||||||
*value = 20;
|
*value = 20;
|
||||||
@ -274,7 +270,7 @@ mod test_rc_mut {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_deep_clone() {
|
fn test_deep_clone() {
|
||||||
let x = rc_mut_from_const(5);
|
let x = RcMut::from_const(5);
|
||||||
let y = x.deep_clone();
|
let y = x.deep_clone();
|
||||||
do x.with_mut_borrow |value| {
|
do x.with_mut_borrow |value| {
|
||||||
*value = 20;
|
*value = 20;
|
||||||
@ -286,7 +282,7 @@ mod test_rc_mut {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn borrow_many() {
|
fn borrow_many() {
|
||||||
let x = rc_mut_from_owned(5);
|
let x = RcMut::from_owned(5);
|
||||||
let y = x.clone();
|
let y = x.clone();
|
||||||
|
|
||||||
do x.with_borrow |a| {
|
do x.with_borrow |a| {
|
||||||
@ -302,7 +298,7 @@ mod test_rc_mut {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn modify() {
|
fn modify() {
|
||||||
let x = rc_mut_from_const(5);
|
let x = RcMut::from_const(5);
|
||||||
let y = x.clone();
|
let y = x.clone();
|
||||||
|
|
||||||
do y.with_mut_borrow |a| {
|
do y.with_mut_borrow |a| {
|
||||||
@ -317,14 +313,14 @@ mod test_rc_mut {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn release_immutable() {
|
fn release_immutable() {
|
||||||
let x = rc_mut_from_owned(5);
|
let x = RcMut::from_owned(5);
|
||||||
do x.with_borrow |_| {}
|
do x.with_borrow |_| {}
|
||||||
do x.with_mut_borrow |_| {}
|
do x.with_mut_borrow |_| {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn release_mutable() {
|
fn release_mutable() {
|
||||||
let x = rc_mut_from_const(5);
|
let x = RcMut::from_const(5);
|
||||||
do x.with_mut_borrow |_| {}
|
do x.with_mut_borrow |_| {}
|
||||||
do x.with_borrow |_| {}
|
do x.with_borrow |_| {}
|
||||||
}
|
}
|
||||||
@ -332,7 +328,7 @@ mod test_rc_mut {
|
|||||||
#[test]
|
#[test]
|
||||||
#[should_fail]
|
#[should_fail]
|
||||||
fn frozen() {
|
fn frozen() {
|
||||||
let x = rc_mut_from_owned(5);
|
let x = RcMut::from_owned(5);
|
||||||
let y = x.clone();
|
let y = x.clone();
|
||||||
|
|
||||||
do x.with_borrow |_| {
|
do x.with_borrow |_| {
|
||||||
@ -344,7 +340,7 @@ mod test_rc_mut {
|
|||||||
#[test]
|
#[test]
|
||||||
#[should_fail]
|
#[should_fail]
|
||||||
fn mutable_dupe() {
|
fn mutable_dupe() {
|
||||||
let x = rc_mut_from_const(5);
|
let x = RcMut::from_const(5);
|
||||||
let y = x.clone();
|
let y = x.clone();
|
||||||
|
|
||||||
do x.with_mut_borrow |_| {
|
do x.with_mut_borrow |_| {
|
||||||
@ -356,7 +352,7 @@ mod test_rc_mut {
|
|||||||
#[test]
|
#[test]
|
||||||
#[should_fail]
|
#[should_fail]
|
||||||
fn mutable_freeze() {
|
fn mutable_freeze() {
|
||||||
let x = rc_mut_from_owned(5);
|
let x = RcMut::from_owned(5);
|
||||||
let y = x.clone();
|
let y = x.clone();
|
||||||
|
|
||||||
do x.with_mut_borrow |_| {
|
do x.with_mut_borrow |_| {
|
||||||
@ -368,7 +364,7 @@ mod test_rc_mut {
|
|||||||
#[test]
|
#[test]
|
||||||
#[should_fail]
|
#[should_fail]
|
||||||
fn restore_freeze() {
|
fn restore_freeze() {
|
||||||
let x = rc_mut_from_const(5);
|
let x = RcMut::from_const(5);
|
||||||
let y = x.clone();
|
let y = x.clone();
|
||||||
|
|
||||||
do x.with_borrow |_| {
|
do x.with_borrow |_| {
|
||||||
|
@ -14,7 +14,7 @@ fn o<T: Send>(_: &T) {}
|
|||||||
fn c<T: Freeze>(_: &T) {}
|
fn c<T: Freeze>(_: &T) {}
|
||||||
|
|
||||||
fn main() {
|
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`
|
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`
|
c(&x); //~ ERROR instantiating a type parameter with an incompatible type `extra::rc::RcMut<int>`, which does not fulfill `Freeze`
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user