Move mutable::Mut to cell::RefCell
This commit is contained in:
parent
c6ca9abcc6
commit
bdfaf04bd5
11 changed files with 335 additions and 350 deletions
|
@ -8,12 +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.
|
||||||
|
|
||||||
//! Runtime move semantics
|
//! Types dealing with dynamic mutability
|
||||||
|
|
||||||
#[missing_doc];
|
#[missing_doc];
|
||||||
|
|
||||||
use cast::transmute_mut;
|
|
||||||
use prelude::*;
|
use prelude::*;
|
||||||
|
use cast;
|
||||||
|
use util::NonCopyable;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
A dynamic, mutable location.
|
A dynamic, mutable location.
|
||||||
|
@ -36,7 +38,7 @@ impl<T> Cell<T> {
|
||||||
|
|
||||||
/// Yields the value, failing if the cell is empty.
|
/// Yields the value, failing if the cell is empty.
|
||||||
pub fn take(&self) -> T {
|
pub fn take(&self) -> T {
|
||||||
let this = unsafe { transmute_mut(self) };
|
let this = unsafe { cast::transmute_mut(self) };
|
||||||
if this.is_empty() {
|
if this.is_empty() {
|
||||||
fail!("attempt to take an empty cell");
|
fail!("attempt to take an empty cell");
|
||||||
}
|
}
|
||||||
|
@ -46,7 +48,7 @@ impl<T> Cell<T> {
|
||||||
|
|
||||||
/// Yields the value if the cell is full, or `None` if it is empty.
|
/// Yields the value if the cell is full, or `None` if it is empty.
|
||||||
pub fn take_opt(&self) -> Option<T> {
|
pub fn take_opt(&self) -> Option<T> {
|
||||||
let this = unsafe { transmute_mut(self) };
|
let this = unsafe { cast::transmute_mut(self) };
|
||||||
this.value.take()
|
this.value.take()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,3 +74,295 @@ fn test_take_empty() {
|
||||||
value_cell.take();
|
value_cell.take();
|
||||||
value_cell.take();
|
value_cell.take();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// A mutable memory location with dynamically checked borrow rules
|
||||||
|
#[no_freeze]
|
||||||
|
pub struct RefCell<T> {
|
||||||
|
priv value: T,
|
||||||
|
priv borrow: BorrowFlag,
|
||||||
|
priv nc: NonCopyable
|
||||||
|
}
|
||||||
|
|
||||||
|
// Values [1, MAX-1] represent the number of `Ref` active
|
||||||
|
// (will not outgrow its range since `uint` is the size of the address space)
|
||||||
|
type BorrowFlag = uint;
|
||||||
|
static UNUSED: BorrowFlag = 0;
|
||||||
|
static WRITING: BorrowFlag = -1;
|
||||||
|
|
||||||
|
impl<T> RefCell<T> {
|
||||||
|
/// Create a new `RefCell` containing `value`
|
||||||
|
pub fn new(value: T) -> RefCell<T> {
|
||||||
|
RefCell {
|
||||||
|
value: value,
|
||||||
|
borrow: UNUSED,
|
||||||
|
nc: NonCopyable
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Consumes the `RefCell`, returning the wrapped value.
|
||||||
|
pub fn unwrap(self) -> T {
|
||||||
|
assert!(self.borrow == UNUSED);
|
||||||
|
self.value
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn as_mut<'a>(&'a self) -> &'a mut RefCell<T> {
|
||||||
|
cast::transmute_mut(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Attempts to immutably borrow the wrapped value.
|
||||||
|
///
|
||||||
|
/// The borrow lasts until the returned `Ref` exits scope. Multiple
|
||||||
|
/// immutable borrows can be taken out at the same time.
|
||||||
|
///
|
||||||
|
/// Returns `None` if the value is currently mutably borrowed.
|
||||||
|
pub fn try_borrow<'a>(&'a self) -> Option<Ref<'a, T>> {
|
||||||
|
match self.borrow {
|
||||||
|
WRITING => None,
|
||||||
|
_ => {
|
||||||
|
unsafe { self.as_mut().borrow += 1; }
|
||||||
|
Some(Ref { parent: self })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Immutably borrows the wrapped value.
|
||||||
|
///
|
||||||
|
/// The borrow lasts until the returned `Ref` exits scope. Multiple
|
||||||
|
/// immutable borrows can be taken out at the same time.
|
||||||
|
///
|
||||||
|
/// # Failure
|
||||||
|
///
|
||||||
|
/// Fails if the value is currently mutably borrowed.
|
||||||
|
pub fn borrow<'a>(&'a self) -> Ref<'a, T> {
|
||||||
|
match self.try_borrow() {
|
||||||
|
Some(ptr) => ptr,
|
||||||
|
None => fail!("RefCell<T> already mutably borrowed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Mutably borrows the wrapped value.
|
||||||
|
///
|
||||||
|
/// The borrow lasts untile the returned `RefMut` exits scope. The value
|
||||||
|
/// cannot be borrowed while this borrow is active.
|
||||||
|
///
|
||||||
|
/// Returns `None` if the value is currently borrowed.
|
||||||
|
pub fn try_borrow_mut<'a>(&'a self) -> Option<RefMut<'a, T>> {
|
||||||
|
match self.borrow {
|
||||||
|
UNUSED => unsafe {
|
||||||
|
let mut_self = self.as_mut();
|
||||||
|
mut_self.borrow = WRITING;
|
||||||
|
Some(RefMut { parent: mut_self })
|
||||||
|
},
|
||||||
|
_ => None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Mutably borrows the wrapped value.
|
||||||
|
///
|
||||||
|
/// The borrow lasts untile the returned `RefMut` exits scope. The value
|
||||||
|
/// cannot be borrowed while this borrow is active.
|
||||||
|
///
|
||||||
|
/// # Failure
|
||||||
|
///
|
||||||
|
/// Fails if the value is currently borrowed.
|
||||||
|
pub fn borrow_mut<'a>(&'a self) -> RefMut<'a, T> {
|
||||||
|
match self.try_borrow_mut() {
|
||||||
|
Some(ptr) => ptr,
|
||||||
|
None => fail!("RefCell<T> already borrowed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Immutably borrows the wrapped value and applies `blk` to it.
|
||||||
|
///
|
||||||
|
/// # Failure
|
||||||
|
///
|
||||||
|
/// Fails if the value is currently mutably borrowed.
|
||||||
|
#[inline]
|
||||||
|
pub fn with<U>(&self, blk: |&T| -> U) -> U {
|
||||||
|
let ptr = self.borrow();
|
||||||
|
blk(ptr.get())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Mutably borrows the wrapped value and applies `blk` to it.
|
||||||
|
///
|
||||||
|
/// # Failure
|
||||||
|
///
|
||||||
|
/// Fails if the value is currently borrowed.
|
||||||
|
#[inline]
|
||||||
|
pub fn with_mut<U>(&self, blk: |&mut T| -> U) -> U {
|
||||||
|
let mut ptr = self.borrow_mut();
|
||||||
|
blk(ptr.get())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Clone> Clone for RefCell<T> {
|
||||||
|
fn clone(&self) -> RefCell<T> {
|
||||||
|
let x = self.borrow();
|
||||||
|
RefCell::new(x.get().clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: DeepClone> DeepClone for RefCell<T> {
|
||||||
|
fn deep_clone(&self) -> RefCell<T> {
|
||||||
|
let x = self.borrow();
|
||||||
|
RefCell::new(x.get().deep_clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Eq> Eq for RefCell<T> {
|
||||||
|
fn eq(&self, other: &RefCell<T>) -> bool {
|
||||||
|
let a = self.borrow();
|
||||||
|
let b = other.borrow();
|
||||||
|
a.get() == b.get()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Wraps a borrowed reference to a value in a `RefCell` box.
|
||||||
|
pub struct Ref<'box, T> {
|
||||||
|
priv parent: &'box RefCell<T>
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe_destructor]
|
||||||
|
impl<'box, T> Drop for Ref<'box, T> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
assert!(self.parent.borrow != WRITING && self.parent.borrow != UNUSED);
|
||||||
|
unsafe { self.parent.as_mut().borrow -= 1; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'box, T> Ref<'box, T> {
|
||||||
|
/// Retrieve an immutable reference to the stored value.
|
||||||
|
#[inline]
|
||||||
|
pub fn get<'a>(&'a self) -> &'a T {
|
||||||
|
&self.parent.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Wraps a mutable borrowed reference to a value in a `RefCell` box.
|
||||||
|
pub struct RefMut<'box, T> {
|
||||||
|
priv parent: &'box mut RefCell<T>
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe_destructor]
|
||||||
|
impl<'box, T> Drop for RefMut<'box, T> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
assert!(self.parent.borrow == WRITING);
|
||||||
|
self.parent.borrow = UNUSED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'box, T> RefMut<'box, T> {
|
||||||
|
/// Retrieve a mutable reference to the stored value.
|
||||||
|
#[inline]
|
||||||
|
pub fn get<'a>(&'a mut self) -> &'a mut T {
|
||||||
|
&mut self.parent.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn double_imm_borrow() {
|
||||||
|
let x = RefCell::new(0);
|
||||||
|
let _b1 = x.borrow();
|
||||||
|
x.borrow();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn no_mut_then_imm_borrow() {
|
||||||
|
let x = RefCell::new(0);
|
||||||
|
let _b1 = x.borrow_mut();
|
||||||
|
assert!(x.try_borrow().is_none());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn no_imm_then_borrow_mut() {
|
||||||
|
let x = RefCell::new(0);
|
||||||
|
let _b1 = x.borrow();
|
||||||
|
assert!(x.try_borrow_mut().is_none());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn no_double_borrow_mut() {
|
||||||
|
let x = RefCell::new(0);
|
||||||
|
let _b1 = x.borrow_mut();
|
||||||
|
assert!(x.try_borrow_mut().is_none());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn imm_release_borrow_mut() {
|
||||||
|
let x = RefCell::new(0);
|
||||||
|
{
|
||||||
|
let _b1 = x.borrow();
|
||||||
|
}
|
||||||
|
x.borrow_mut();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn mut_release_borrow_mut() {
|
||||||
|
let x = RefCell::new(0);
|
||||||
|
{
|
||||||
|
let _b1 = x.borrow_mut();
|
||||||
|
}
|
||||||
|
x.borrow();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn double_borrow_single_release_no_borrow_mut() {
|
||||||
|
let x = RefCell::new(0);
|
||||||
|
let _b1 = x.borrow();
|
||||||
|
{
|
||||||
|
let _b2 = x.borrow();
|
||||||
|
}
|
||||||
|
assert!(x.try_borrow_mut().is_none());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn with_ok() {
|
||||||
|
let x = RefCell::new(0);
|
||||||
|
assert_eq!(1, x.with(|x| *x+1));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_fail]
|
||||||
|
fn mut_borrow_with() {
|
||||||
|
let x = RefCell::new(0);
|
||||||
|
let _b1 = x.borrow_mut();
|
||||||
|
x.with(|x| *x+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn borrow_with() {
|
||||||
|
let x = RefCell::new(0);
|
||||||
|
let _b1 = x.borrow();
|
||||||
|
assert_eq!(1, x.with(|x| *x+1));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn with_mut_ok() {
|
||||||
|
let x = RefCell::new(0);
|
||||||
|
x.with_mut(|x| *x += 1);
|
||||||
|
let b = x.borrow();
|
||||||
|
assert_eq!(1, *b.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_fail]
|
||||||
|
fn borrow_with_mut() {
|
||||||
|
let x = RefCell::new(0);
|
||||||
|
let _b = x.borrow();
|
||||||
|
x.with_mut(|x| *x += 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_fail]
|
||||||
|
fn discard_doesnt_unborrow() {
|
||||||
|
let x = RefCell::new(0);
|
||||||
|
let _b = x.borrow();
|
||||||
|
let _ = _b;
|
||||||
|
let _b = x.borrow_mut();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -55,26 +55,26 @@ impl<T: DeepClone + Send + 'static> DeepClone for Gc<T> {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use cell::Cell;
|
use cell::RefCell;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_clone() {
|
fn test_clone() {
|
||||||
let x = Gc::new(Cell::new(5));
|
let x = Gc::new(RefCell::new(5));
|
||||||
let y = x.clone();
|
let y = x.clone();
|
||||||
do x.borrow().with_mut_ref |inner| {
|
do x.borrow().with_mut |inner| {
|
||||||
*inner = 20;
|
*inner = 20;
|
||||||
}
|
}
|
||||||
assert_eq!(y.borrow().take(), 20);
|
assert_eq!(y.borrow().with(|x| *x), 20);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_deep_clone() {
|
fn test_deep_clone() {
|
||||||
let x = Gc::new(Cell::new(5));
|
let x = Gc::new(RefCell::new(5));
|
||||||
let y = x.deep_clone();
|
let y = x.deep_clone();
|
||||||
do x.borrow().with_mut_ref |inner| {
|
do x.borrow().with_mut |inner| {
|
||||||
*inner = 20;
|
*inner = 20;
|
||||||
}
|
}
|
||||||
assert_eq!(y.borrow().take(), 5);
|
assert_eq!(y.borrow().with(|x| *x), 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -164,7 +164,6 @@ pub mod result;
|
||||||
pub mod either;
|
pub mod either;
|
||||||
pub mod hashmap;
|
pub mod hashmap;
|
||||||
pub mod cell;
|
pub mod cell;
|
||||||
pub mod mutable;
|
|
||||||
pub mod trie;
|
pub mod trie;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,307 +0,0 @@
|
||||||
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
|
|
||||||
// file at the top-level directory of this distribution and at
|
|
||||||
// http://rust-lang.org/COPYRIGHT.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
||||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
||||||
// option. This file may not be copied, modified, or distributed
|
|
||||||
// except according to those terms.
|
|
||||||
|
|
||||||
//! A mutable memory location with dynamically checked borrow rules
|
|
||||||
|
|
||||||
use prelude::*;
|
|
||||||
|
|
||||||
use cast;
|
|
||||||
use util::NonCopyable;
|
|
||||||
|
|
||||||
/// A mutable memory location with dynamically checked borrow rules
|
|
||||||
#[no_freeze]
|
|
||||||
pub struct Mut<T> {
|
|
||||||
priv value: T,
|
|
||||||
priv borrow: BorrowFlag,
|
|
||||||
priv nc: NonCopyable
|
|
||||||
}
|
|
||||||
|
|
||||||
// Values [1, MAX-1] represent the number of `Ref` active
|
|
||||||
// (will not outgrow its range since `uint` is the size of the address space)
|
|
||||||
type BorrowFlag = uint;
|
|
||||||
static UNUSED: BorrowFlag = 0;
|
|
||||||
static WRITING: BorrowFlag = -1;
|
|
||||||
|
|
||||||
impl<T> Mut<T> {
|
|
||||||
/// Create a new `Mut` containing `value`
|
|
||||||
pub fn new(value: T) -> Mut<T> {
|
|
||||||
Mut {
|
|
||||||
value: value,
|
|
||||||
borrow: UNUSED,
|
|
||||||
nc: NonCopyable
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Consumes the `Mut`, returning the wrapped value.
|
|
||||||
pub fn unwrap(self) -> T {
|
|
||||||
assert!(self.borrow == UNUSED);
|
|
||||||
self.value
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe fn as_mut<'a>(&'a self) -> &'a mut Mut<T> {
|
|
||||||
cast::transmute_mut(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Attempts to immutably borrow the wrapped value.
|
|
||||||
///
|
|
||||||
/// The borrow lasts until the returned `Ref` exits scope. Multiple
|
|
||||||
/// immutable borrows can be taken out at the same time.
|
|
||||||
///
|
|
||||||
/// Returns `None` if the value is currently mutably borrowed.
|
|
||||||
pub fn try_borrow<'a>(&'a self) -> Option<Ref<'a, T>> {
|
|
||||||
match self.borrow {
|
|
||||||
WRITING => None,
|
|
||||||
_ => {
|
|
||||||
unsafe { self.as_mut().borrow += 1; }
|
|
||||||
Some(Ref { parent: self })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Immutably borrows the wrapped value.
|
|
||||||
///
|
|
||||||
/// The borrow lasts until the returned `Ref` exits scope. Multiple
|
|
||||||
/// immutable borrows can be taken out at the same time.
|
|
||||||
///
|
|
||||||
/// # Failure
|
|
||||||
///
|
|
||||||
/// Fails if the value is currently mutably borrowed.
|
|
||||||
pub fn borrow<'a>(&'a self) -> Ref<'a, T> {
|
|
||||||
match self.try_borrow() {
|
|
||||||
Some(ptr) => ptr,
|
|
||||||
None => fail!("Mut<T> already mutably borrowed")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Mutably borrows the wrapped value.
|
|
||||||
///
|
|
||||||
/// The borrow lasts untile the returned `RefMut` exits scope. The value
|
|
||||||
/// cannot be borrowed while this borrow is active.
|
|
||||||
///
|
|
||||||
/// Returns `None` if the value is currently borrowed.
|
|
||||||
pub fn try_borrow_mut<'a>(&'a self) -> Option<RefMut<'a, T>> {
|
|
||||||
match self.borrow {
|
|
||||||
UNUSED => unsafe {
|
|
||||||
let mut_self = self.as_mut();
|
|
||||||
mut_self.borrow = WRITING;
|
|
||||||
Some(RefMut { parent: mut_self })
|
|
||||||
},
|
|
||||||
_ => None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Mutably borrows the wrapped value.
|
|
||||||
///
|
|
||||||
/// The borrow lasts untile the returned `RefMut` exits scope. The value
|
|
||||||
/// cannot be borrowed while this borrow is active.
|
|
||||||
///
|
|
||||||
/// # Failure
|
|
||||||
///
|
|
||||||
/// Fails if the value is currently borrowed.
|
|
||||||
pub fn borrow_mut<'a>(&'a self) -> RefMut<'a, T> {
|
|
||||||
match self.try_borrow_mut() {
|
|
||||||
Some(ptr) => ptr,
|
|
||||||
None => fail!("Mut<T> already borrowed")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Immutably borrows the wrapped value and applies `blk` to it.
|
|
||||||
///
|
|
||||||
/// # Failure
|
|
||||||
///
|
|
||||||
/// Fails if the value is currently mutably borrowed.
|
|
||||||
#[inline]
|
|
||||||
pub fn with<U>(&self, blk: |&T| -> U) -> U {
|
|
||||||
let ptr = self.borrow();
|
|
||||||
blk(ptr.get())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Mutably borrows the wrapped value and applies `blk` to it.
|
|
||||||
///
|
|
||||||
/// # Failure
|
|
||||||
///
|
|
||||||
/// Fails if the value is currently borrowed.
|
|
||||||
#[inline]
|
|
||||||
pub fn with_mut<U>(&self, blk: |&mut T| -> U) -> U {
|
|
||||||
let mut ptr = self.borrow_mut();
|
|
||||||
blk(ptr.get())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Clone> Clone for Mut<T> {
|
|
||||||
fn clone(&self) -> Mut<T> {
|
|
||||||
let x = self.borrow();
|
|
||||||
Mut::new(x.get().clone())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: DeepClone> DeepClone for Mut<T> {
|
|
||||||
fn deep_clone(&self) -> Mut<T> {
|
|
||||||
let x = self.borrow();
|
|
||||||
Mut::new(x.get().deep_clone())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Eq> Eq for Mut<T> {
|
|
||||||
fn eq(&self, other: &Mut<T>) -> bool {
|
|
||||||
let a = self.borrow();
|
|
||||||
let b = other.borrow();
|
|
||||||
a.get() == b.get()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Wraps a borrowed reference to a value in a `Mut` box.
|
|
||||||
pub struct Ref<'box, T> {
|
|
||||||
priv parent: &'box Mut<T>
|
|
||||||
}
|
|
||||||
|
|
||||||
#[unsafe_destructor]
|
|
||||||
impl<'box, T> Drop for Ref<'box, T> {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
assert!(self.parent.borrow != WRITING && self.parent.borrow != UNUSED);
|
|
||||||
unsafe { self.parent.as_mut().borrow -= 1; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'box, T> Ref<'box, T> {
|
|
||||||
/// Retrieve an immutable reference to the stored value.
|
|
||||||
#[inline]
|
|
||||||
pub fn get<'a>(&'a self) -> &'a T {
|
|
||||||
&self.parent.value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Wraps a mutable borrowed reference to a value in a `Mut` box.
|
|
||||||
pub struct RefMut<'box, T> {
|
|
||||||
priv parent: &'box mut Mut<T>
|
|
||||||
}
|
|
||||||
|
|
||||||
#[unsafe_destructor]
|
|
||||||
impl<'box, T> Drop for RefMut<'box, T> {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
assert!(self.parent.borrow == WRITING);
|
|
||||||
self.parent.borrow = UNUSED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'box, T> RefMut<'box, T> {
|
|
||||||
/// Retrieve a mutable reference to the stored value.
|
|
||||||
#[inline]
|
|
||||||
pub fn get<'a>(&'a mut self) -> &'a mut T {
|
|
||||||
&mut self.parent.value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn double_imm_borrow() {
|
|
||||||
let x = Mut::new(0);
|
|
||||||
let _b1 = x.borrow();
|
|
||||||
x.borrow();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn no_mut_then_imm_borrow() {
|
|
||||||
let x = Mut::new(0);
|
|
||||||
let _b1 = x.borrow_mut();
|
|
||||||
assert!(x.try_borrow().is_none());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn no_imm_then_borrow_mut() {
|
|
||||||
let x = Mut::new(0);
|
|
||||||
let _b1 = x.borrow();
|
|
||||||
assert!(x.try_borrow_mut().is_none());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn no_double_borrow_mut() {
|
|
||||||
let x = Mut::new(0);
|
|
||||||
let _b1 = x.borrow_mut();
|
|
||||||
assert!(x.try_borrow_mut().is_none());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn imm_release_borrow_mut() {
|
|
||||||
let x = Mut::new(0);
|
|
||||||
{
|
|
||||||
let _b1 = x.borrow();
|
|
||||||
}
|
|
||||||
x.borrow_mut();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn mut_release_borrow_mut() {
|
|
||||||
let x = Mut::new(0);
|
|
||||||
{
|
|
||||||
let _b1 = x.borrow_mut();
|
|
||||||
}
|
|
||||||
x.borrow();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn double_borrow_single_release_no_borrow_mut() {
|
|
||||||
let x = Mut::new(0);
|
|
||||||
let _b1 = x.borrow();
|
|
||||||
{
|
|
||||||
let _b2 = x.borrow();
|
|
||||||
}
|
|
||||||
assert!(x.try_borrow_mut().is_none());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn with_ok() {
|
|
||||||
let x = Mut::new(0);
|
|
||||||
assert_eq!(1, x.with(|x| *x+1));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[should_fail]
|
|
||||||
fn mut_borrow_with() {
|
|
||||||
let x = Mut::new(0);
|
|
||||||
let _b1 = x.borrow_mut();
|
|
||||||
x.with(|x| *x+1);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn borrow_with() {
|
|
||||||
let x = Mut::new(0);
|
|
||||||
let _b1 = x.borrow();
|
|
||||||
assert_eq!(1, x.with(|x| *x+1));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn with_mut_ok() {
|
|
||||||
let x = Mut::new(0);
|
|
||||||
x.with_mut(|x| *x += 1);
|
|
||||||
let b = x.borrow();
|
|
||||||
assert_eq!(1, *b.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[should_fail]
|
|
||||||
fn borrow_with_mut() {
|
|
||||||
let x = Mut::new(0);
|
|
||||||
let _b = x.borrow();
|
|
||||||
x.with_mut(|x| *x += 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[should_fail]
|
|
||||||
fn discard_doesnt_unborrow() {
|
|
||||||
let x = Mut::new(0);
|
|
||||||
let _b = x.borrow();
|
|
||||||
let _ = _b;
|
|
||||||
let _b = x.borrow_mut();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -21,7 +21,7 @@ use unstable::intrinsics::transmute;
|
||||||
use ops::Drop;
|
use ops::Drop;
|
||||||
use kinds::{Freeze, Send};
|
use kinds::{Freeze, Send};
|
||||||
use clone::{Clone, DeepClone};
|
use clone::{Clone, DeepClone};
|
||||||
use mutable::Mut;
|
use cell::RefCell;
|
||||||
|
|
||||||
struct RcBox<T> {
|
struct RcBox<T> {
|
||||||
value: T,
|
value: T,
|
||||||
|
@ -55,10 +55,10 @@ impl<T: Send> Rc<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Freeze> Rc<Mut<T>> {
|
impl<T: Freeze> Rc<RefCell<T>> {
|
||||||
/// Construct a new reference-counted box from a `Mut`-wrapped `Freeze` value
|
/// Construct a new reference-counted box from a `RefCell`-wrapped `Freeze` value
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_mut(value: Mut<T>) -> Rc<Mut<T>> {
|
pub fn from_mut(value: RefCell<T>) -> Rc<RefCell<T>> {
|
||||||
unsafe {
|
unsafe {
|
||||||
Rc::new_unchecked(value)
|
Rc::new_unchecked(value)
|
||||||
}
|
}
|
||||||
|
@ -116,11 +116,11 @@ impl<T> Drop for Rc<T> {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test_rc {
|
mod test_rc {
|
||||||
use super::*;
|
use super::*;
|
||||||
use mutable::Mut;
|
use cell::RefCell;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_clone() {
|
fn test_clone() {
|
||||||
let x = Rc::from_send(Mut::new(5));
|
let x = Rc::from_send(RefCell::new(5));
|
||||||
let y = x.clone();
|
let y = x.clone();
|
||||||
do x.borrow().with_mut |inner| {
|
do x.borrow().with_mut |inner| {
|
||||||
*inner = 20;
|
*inner = 20;
|
||||||
|
@ -130,7 +130,7 @@ mod test_rc {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_deep_clone() {
|
fn test_deep_clone() {
|
||||||
let x = Rc::from_send(Mut::new(5));
|
let x = Rc::from_send(RefCell::new(5));
|
||||||
let y = x.deep_clone();
|
let y = x.deep_clone();
|
||||||
do x.borrow().with_mut |inner| {
|
do x.borrow().with_mut |inner| {
|
||||||
*inner = 20;
|
*inner = 20;
|
||||||
|
@ -161,6 +161,6 @@ mod test_rc {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_from_mut() {
|
fn test_from_mut() {
|
||||||
let a = 10;
|
let a = 10;
|
||||||
let _x = Rc::from_mut(Mut::new(&a));
|
let _x = Rc::from_mut(RefCell::new(&a));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,10 +25,9 @@ use unstable::sync::UnsafeArc;
|
||||||
use util;
|
use util;
|
||||||
use util::Void;
|
use util::Void;
|
||||||
use comm::{GenericChan, GenericSmartChan, GenericPort, Peekable, SendDeferred};
|
use comm::{GenericChan, GenericSmartChan, GenericPort, Peekable, SendDeferred};
|
||||||
use cell::Cell;
|
use cell::{Cell, RefCell};
|
||||||
use clone::Clone;
|
use clone::Clone;
|
||||||
use tuple::ImmutableTuple;
|
use tuple::ImmutableTuple;
|
||||||
use mutable::Mut;
|
|
||||||
|
|
||||||
/// A combined refcount / BlockedTask-as-uint pointer.
|
/// A combined refcount / BlockedTask-as-uint pointer.
|
||||||
///
|
///
|
||||||
|
@ -433,20 +432,20 @@ type StreamPortOne<T> = PortOne<StreamPayload<T>>;
|
||||||
|
|
||||||
/// A channel with unbounded size.
|
/// A channel with unbounded size.
|
||||||
pub struct Chan<T> {
|
pub struct Chan<T> {
|
||||||
// FIXME #5372. Using Mut because we don't take &mut self
|
// FIXME #5372. Using RefCell because we don't take &mut self
|
||||||
next: Mut<StreamChanOne<T>>
|
next: RefCell<StreamChanOne<T>>
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An port with unbounded size.
|
/// An port with unbounded size.
|
||||||
pub struct Port<T> {
|
pub struct Port<T> {
|
||||||
// FIXME #5372. Using Mut because we don't take &mut self
|
// FIXME #5372. Using RefCell because we don't take &mut self
|
||||||
next: Mut<Option<StreamPortOne<T>>>
|
next: RefCell<Option<StreamPortOne<T>>>
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn stream<T: Send>() -> (Port<T>, Chan<T>) {
|
pub fn stream<T: Send>() -> (Port<T>, Chan<T>) {
|
||||||
let (pone, cone) = oneshot();
|
let (pone, cone) = oneshot();
|
||||||
let port = Port { next: Mut::new(Some(pone)) };
|
let port = Port { next: RefCell::new(Some(pone)) };
|
||||||
let chan = Chan { next: Mut::new(cone) };
|
let chan = Chan { next: RefCell::new(cone) };
|
||||||
return (port, chan);
|
return (port, chan);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,21 +9,21 @@
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::mutable::Mut;
|
use std::cell::RefCell;
|
||||||
|
|
||||||
trait Foo
|
trait Foo
|
||||||
{
|
{
|
||||||
fn set(&mut self, v: Rc<Mut<A>>);
|
fn set(&mut self, v: Rc<RefCell<A>>);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct B
|
struct B
|
||||||
{
|
{
|
||||||
v: Option<Rc<Mut<A>>>
|
v: Option<Rc<RefCell<A>>>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Foo for B
|
impl Foo for B
|
||||||
{
|
{
|
||||||
fn set(&mut self, v: Rc<Mut<A>>)
|
fn set(&mut self, v: Rc<RefCell<A>>)
|
||||||
{
|
{
|
||||||
self.v = Some(v);
|
self.v = Some(v);
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ 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 = Rc::from_send(Mut::new(a));
|
let v = Rc::from_send(RefCell::new(a));
|
||||||
let w = v.clone();
|
let w = v.clone();
|
||||||
let b = v.borrow();
|
let b = v.borrow();
|
||||||
let mut b = b.borrow_mut();
|
let mut b = b.borrow_mut();
|
||||||
|
|
|
@ -8,10 +8,10 @@
|
||||||
// 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::mutable::Mut;
|
use std::cell::RefCell;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let m = Mut::new(0);
|
let m = RefCell::new(0);
|
||||||
let mut b = m.borrow_mut();
|
let mut b = m.borrow_mut();
|
||||||
let b1 = b.get();
|
let b1 = b.get();
|
||||||
let b2 = b.get(); //~ ERROR cannot borrow `b` as mutable more than once at a time
|
let b2 = b.get(); //~ ERROR cannot borrow `b` as mutable more than once at a time
|
||||||
|
|
|
@ -8,11 +8,11 @@
|
||||||
// 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::mutable::Mut;
|
use std::cell::RefCell;
|
||||||
|
|
||||||
fn f<T: Freeze>(_: T) {}
|
fn f<T: Freeze>(_: T) {}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let x = Mut::new(0);
|
let x = RefCell::new(0);
|
||||||
f(x); //~ ERROR: which does not fulfill `Freeze`
|
f(x); //~ ERROR: which does not fulfill `Freeze`
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,10 +8,10 @@
|
||||||
// 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::mutable::Mut;
|
use std::cell::RefCell;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let m = Mut::new(0);
|
let m = RefCell::new(0);
|
||||||
let p;
|
let p;
|
||||||
{
|
{
|
||||||
let b = m.borrow();
|
let b = m.borrow();
|
||||||
|
|
|
@ -8,14 +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::mutable::Mut;
|
use std::cell::RefCell;
|
||||||
use std::rc::Rc;
|
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 = Rc::from_send(Mut::new(0));
|
let x = Rc::from_send(RefCell::new(0));
|
||||||
o(&x); //~ ERROR instantiating a type parameter with an incompatible type `std::rc::Rc<std::mutable::Mut<int>>`, which does not fulfill `Send`
|
o(&x); //~ ERROR instantiating a type parameter with an incompatible type `std::rc::Rc<std::cell::RefCell<int>>`, which does not fulfill `Send`
|
||||||
c(&x); //~ ERROR instantiating a type parameter with an incompatible type `std::rc::Rc<std::mutable::Mut<int>>`, which does not fulfill `Freeze`
|
c(&x); //~ ERROR instantiating a type parameter with an incompatible type `std::rc::Rc<std::cell::RefCell<int>>`, which does not fulfill `Freeze`
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue