Remove RcMut
Rc<Mut<T>> should be used instead
This commit is contained in:
parent
0fade3a714
commit
7c9daa8ff7
3 changed files with 14 additions and 247 deletions
237
src/libstd/rc.rs
237
src/libstd/rc.rs
|
@ -14,10 +14,6 @@ The `Rc` type provides shared ownership of an immutable value. Destruction is de
|
||||||
will occur as soon as the last owner is gone. It is marked as non-sendable because it avoids the
|
will occur as soon as the last owner is gone. It is marked as non-sendable because it avoids the
|
||||||
overhead of atomic reference counting.
|
overhead of atomic reference counting.
|
||||||
|
|
||||||
The `RcMut` type provides shared ownership of a mutable value. Since multiple owners prevent
|
|
||||||
inherited mutability, a dynamic freezing check is used to maintain the invariant that an `&mut`
|
|
||||||
reference is a unique handle and the type is marked as non-`Freeze`.
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use ptr::RawPtr;
|
use ptr::RawPtr;
|
||||||
|
@ -151,236 +147,3 @@ mod test_rc {
|
||||||
assert_eq!(**x.borrow(), 5);
|
assert_eq!(**x.borrow(), 5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[deriving(Eq)]
|
|
||||||
enum Borrow {
|
|
||||||
Mutable,
|
|
||||||
Immutable,
|
|
||||||
Nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
struct RcMutBox<T> {
|
|
||||||
value: T,
|
|
||||||
count: uint,
|
|
||||||
borrow: Borrow
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Mutable reference counted pointer type
|
|
||||||
#[no_send]
|
|
||||||
#[no_freeze]
|
|
||||||
#[unsafe_no_drop_flag]
|
|
||||||
pub struct RcMut<T> {
|
|
||||||
priv ptr: *mut RcMutBox<T>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Freeze> RcMut<T> {
|
|
||||||
/// Construct a new mutable reference-counted box from a `Freeze` value
|
|
||||||
#[inline]
|
|
||||||
pub fn new(value: T) -> RcMut<T> {
|
|
||||||
unsafe { RcMut::new_unchecked(value) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Send> RcMut<T> {
|
|
||||||
/// Construct a new mutable reference-counted box from a `Send` value
|
|
||||||
#[inline]
|
|
||||||
pub fn from_send(value: T) -> RcMut<T> {
|
|
||||||
unsafe { RcMut::new_unchecked(value) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> RcMut<T> {
|
|
||||||
/// Unsafety construct a new mutable reference-counted box from any value.
|
|
||||||
///
|
|
||||||
/// It is possible to create cycles, which will leak, and may interact
|
|
||||||
/// poorly with managed pointers.
|
|
||||||
#[inline]
|
|
||||||
pub unsafe fn new_unchecked(value: T) -> RcMut<T> {
|
|
||||||
RcMut{ptr: transmute(~RcMutBox{value: value, count: 1, borrow: Nothing})}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> RcMut<T> {
|
|
||||||
/// Fails if there is already a mutable borrow of the box
|
|
||||||
#[inline]
|
|
||||||
pub fn with_borrow<U>(&self, f: |&T| -> U) -> U {
|
|
||||||
unsafe {
|
|
||||||
assert!((*self.ptr).borrow != Mutable);
|
|
||||||
let previous = (*self.ptr).borrow;
|
|
||||||
(*self.ptr).borrow = Immutable;
|
|
||||||
let res = f(&(*self.ptr).value);
|
|
||||||
(*self.ptr).borrow = previous;
|
|
||||||
res
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Fails if there is already a mutable or immutable borrow of the box
|
|
||||||
#[inline]
|
|
||||||
pub fn with_mut_borrow<U>(&self, f: |&mut T| -> U) -> U {
|
|
||||||
unsafe {
|
|
||||||
assert_eq!((*self.ptr).borrow, Nothing);
|
|
||||||
(*self.ptr).borrow = Mutable;
|
|
||||||
let res = f(&mut (*self.ptr).value);
|
|
||||||
(*self.ptr).borrow = Nothing;
|
|
||||||
res
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[unsafe_destructor]
|
|
||||||
impl<T> Drop for RcMut<T> {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
unsafe {
|
|
||||||
if self.ptr.is_not_null() {
|
|
||||||
(*self.ptr).count -= 1;
|
|
||||||
if (*self.ptr).count == 0 {
|
|
||||||
let _: ~RcMutBox<T> = transmute(self.ptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Clone for RcMut<T> {
|
|
||||||
/// Return a shallow copy of the reference counted pointer.
|
|
||||||
#[inline]
|
|
||||||
fn clone(&self) -> RcMut<T> {
|
|
||||||
unsafe {
|
|
||||||
(*self.ptr).count += 1;
|
|
||||||
RcMut{ptr: self.ptr}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: DeepClone> DeepClone for RcMut<T> {
|
|
||||||
/// Return a deep copy of the reference counted pointer.
|
|
||||||
#[inline]
|
|
||||||
fn deep_clone(&self) -> RcMut<T> {
|
|
||||||
do self.with_borrow |x| {
|
|
||||||
// FIXME: #6497: should avoid freeze (slow)
|
|
||||||
unsafe { RcMut::new_unchecked(x.deep_clone()) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test_rc_mut {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_clone() {
|
|
||||||
let x = RcMut::from_send(5);
|
|
||||||
let y = x.clone();
|
|
||||||
do x.with_mut_borrow |value| {
|
|
||||||
*value = 20;
|
|
||||||
}
|
|
||||||
do y.with_borrow |value| {
|
|
||||||
assert_eq!(*value, 20);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_deep_clone() {
|
|
||||||
let x = RcMut::new(5);
|
|
||||||
let y = x.deep_clone();
|
|
||||||
do x.with_mut_borrow |value| {
|
|
||||||
*value = 20;
|
|
||||||
}
|
|
||||||
do y.with_borrow |value| {
|
|
||||||
assert_eq!(*value, 5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn borrow_many() {
|
|
||||||
let x = RcMut::from_send(5);
|
|
||||||
let y = x.clone();
|
|
||||||
|
|
||||||
do x.with_borrow |a| {
|
|
||||||
assert_eq!(*a, 5);
|
|
||||||
do y.with_borrow |b| {
|
|
||||||
assert_eq!(*b, 5);
|
|
||||||
do x.with_borrow |c| {
|
|
||||||
assert_eq!(*c, 5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn modify() {
|
|
||||||
let x = RcMut::new(5);
|
|
||||||
let y = x.clone();
|
|
||||||
|
|
||||||
do y.with_mut_borrow |a| {
|
|
||||||
assert_eq!(*a, 5);
|
|
||||||
*a = 6;
|
|
||||||
}
|
|
||||||
|
|
||||||
do x.with_borrow |a| {
|
|
||||||
assert_eq!(*a, 6);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn release_immutable() {
|
|
||||||
let x = RcMut::from_send(5);
|
|
||||||
do x.with_borrow |_| {}
|
|
||||||
do x.with_mut_borrow |_| {}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn release_mutable() {
|
|
||||||
let x = RcMut::new(5);
|
|
||||||
do x.with_mut_borrow |_| {}
|
|
||||||
do x.with_borrow |_| {}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[should_fail]
|
|
||||||
fn frozen() {
|
|
||||||
let x = RcMut::from_send(5);
|
|
||||||
let y = x.clone();
|
|
||||||
|
|
||||||
do x.with_borrow |_| {
|
|
||||||
do y.with_mut_borrow |_| {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[should_fail]
|
|
||||||
fn mutable_dupe() {
|
|
||||||
let x = RcMut::new(5);
|
|
||||||
let y = x.clone();
|
|
||||||
|
|
||||||
do x.with_mut_borrow |_| {
|
|
||||||
do y.with_mut_borrow |_| {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[should_fail]
|
|
||||||
fn mutable_freeze() {
|
|
||||||
let x = RcMut::from_send(5);
|
|
||||||
let y = x.clone();
|
|
||||||
|
|
||||||
do x.with_mut_borrow |_| {
|
|
||||||
do y.with_borrow |_| {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[should_fail]
|
|
||||||
fn restore_freeze() {
|
|
||||||
let x = RcMut::new(5);
|
|
||||||
let y = x.clone();
|
|
||||||
|
|
||||||
do x.with_borrow |_| {
|
|
||||||
do x.with_borrow |_| {}
|
|
||||||
do y.with_mut_borrow |_| {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -8,21 +8,22 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use std::rc::RcMut;
|
use std::rc::Rc;
|
||||||
|
use std::mutable::Mut;
|
||||||
|
|
||||||
trait Foo
|
trait Foo
|
||||||
{
|
{
|
||||||
fn set(&mut self, v: RcMut<A>);
|
fn set(&mut self, v: Rc<Mut<A>>);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct B
|
struct B
|
||||||
{
|
{
|
||||||
v: Option<RcMut<A>>
|
v: Option<Rc<Mut<A>>>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Foo for B
|
impl Foo for B
|
||||||
{
|
{
|
||||||
fn set(&mut self, v: RcMut<A>)
|
fn set(&mut self, v: Rc<Mut<A>>)
|
||||||
{
|
{
|
||||||
self.v = Some(v);
|
self.v = Some(v);
|
||||||
}
|
}
|
||||||
|
@ -36,7 +37,9 @@ struct A
|
||||||
fn main()
|
fn main()
|
||||||
{
|
{
|
||||||
let a = A {v: ~B{v: None} as ~Foo}; //~ ERROR cannot pack type `~B`, which does not fulfill `Send`
|
let a = A {v: ~B{v: None} as ~Foo}; //~ ERROR cannot pack type `~B`, which does not fulfill `Send`
|
||||||
let v = RcMut::new(a); //~ ERROR instantiating a type parameter with an incompatible type
|
let v = Rc::from_send(Mut::new(a));
|
||||||
let w = v.clone();
|
let w = v.clone();
|
||||||
v.with_mut_borrow(|p| {p.v.set(w.clone());})
|
let b = v.borrow();
|
||||||
|
let mut b = b.borrow_mut();
|
||||||
|
b.get().v.set(w.clone());
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,13 +8,14 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use std::rc::RcMut;
|
use std::mutable::Mut;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
fn o<T: Send>(_: &T) {}
|
fn o<T: Send>(_: &T) {}
|
||||||
fn c<T: Freeze>(_: &T) {}
|
fn c<T: Freeze>(_: &T) {}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let x = RcMut::from_send(0);
|
let x = Rc::from_send(Mut::new(0));
|
||||||
o(&x); //~ ERROR instantiating a type parameter with an incompatible type `std::rc::RcMut<int>`, which does not fulfill `Send`
|
o(&x); //~ ERROR instantiating a type parameter with an incompatible type `std::rc::Rc<std::mutable::Mut<int>>`, which does not fulfill `Send`
|
||||||
c(&x); //~ ERROR instantiating a type parameter with an incompatible type `std::rc::RcMut<int>`, which does not fulfill `Freeze`
|
c(&x); //~ ERROR instantiating a type parameter with an incompatible type `std::rc::Rc<std::mutable::Mut<int>>`, which does not fulfill `Freeze`
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue