2013-05-30 05:16:33 -05:00
|
|
|
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
|
2012-12-03 18:48:01 -06:00
|
|
|
// 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.
|
|
|
|
|
2013-11-21 23:30:34 -06:00
|
|
|
//! Types dealing with dynamic mutability
|
2013-03-24 20:59:04 -05:00
|
|
|
|
2014-02-28 03:23:06 -06:00
|
|
|
use cast;
|
2014-03-05 00:19:14 -06:00
|
|
|
use clone::Clone;
|
2014-02-02 18:32:52 -06:00
|
|
|
use cmp::Eq;
|
2014-02-28 03:23:06 -06:00
|
|
|
use fmt;
|
|
|
|
use kinds::{marker, Pod};
|
2014-02-26 15:07:23 -06:00
|
|
|
use ops::{Deref, DerefMut, Drop};
|
2014-02-06 18:00:49 -06:00
|
|
|
use option::{None, Option, Some};
|
2014-03-10 16:55:37 -05:00
|
|
|
use ty::Unsafe;
|
2013-11-21 23:30:34 -06:00
|
|
|
|
2013-12-11 16:54:27 -06:00
|
|
|
/// A mutable memory location that admits only `Pod` data.
|
|
|
|
pub struct Cell<T> {
|
2014-03-10 16:55:37 -05:00
|
|
|
priv value: Unsafe<T>,
|
2014-03-20 22:24:31 -05:00
|
|
|
priv marker1: marker::NoFreeze,
|
|
|
|
priv marker2: marker::NoShare,
|
2013-12-11 16:54:27 -06:00
|
|
|
}
|
|
|
|
|
2014-01-22 13:03:02 -06:00
|
|
|
impl<T:Pod> Cell<T> {
|
2013-12-11 16:54:27 -06:00
|
|
|
/// Creates a new `Cell` containing the given value.
|
|
|
|
pub fn new(value: T) -> Cell<T> {
|
|
|
|
Cell {
|
2014-03-20 22:24:31 -05:00
|
|
|
value: Unsafe::new(value),
|
|
|
|
marker1: marker::NoFreeze,
|
|
|
|
marker2: marker::NoShare,
|
2013-12-11 16:54:27 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns a copy of the contained value.
|
|
|
|
#[inline]
|
|
|
|
pub fn get(&self) -> T {
|
2014-03-10 16:55:37 -05:00
|
|
|
unsafe{ *self.value.get() }
|
2013-12-11 16:54:27 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Sets the contained value.
|
|
|
|
#[inline]
|
|
|
|
pub fn set(&self, value: T) {
|
|
|
|
unsafe {
|
2014-03-10 16:55:37 -05:00
|
|
|
*self.value.get() = value;
|
2013-12-11 16:54:27 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-22 13:03:02 -06:00
|
|
|
impl<T:Pod> Clone for Cell<T> {
|
|
|
|
fn clone(&self) -> Cell<T> {
|
|
|
|
Cell::new(self.get())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-02-24 19:38:40 -06:00
|
|
|
impl<T:Eq + Pod> Eq for Cell<T> {
|
|
|
|
fn eq(&self, other: &Cell<T>) -> bool {
|
|
|
|
self.get() == other.get()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-02-28 03:23:06 -06:00
|
|
|
impl<T: fmt::Show> fmt::Show for Cell<T> {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
2014-03-10 16:55:37 -05:00
|
|
|
write!(f.buf, r"Cell \{ value: {} \}", unsafe{*&self.value.get()})
|
2014-02-28 03:23:06 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-21 23:30:34 -06:00
|
|
|
/// A mutable memory location with dynamically checked borrow rules
|
|
|
|
pub struct RefCell<T> {
|
2014-03-10 16:55:37 -05:00
|
|
|
priv value: Unsafe<T>,
|
2013-11-21 23:30:34 -06:00
|
|
|
priv borrow: BorrowFlag,
|
2014-03-20 22:24:31 -05:00
|
|
|
priv marker1: marker::NoFreeze,
|
|
|
|
priv marker2: marker::NoPod,
|
|
|
|
priv marker3: marker::NoShare,
|
2013-11-21 23:30:34 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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 {
|
2014-03-20 22:24:31 -05:00
|
|
|
marker1: marker::NoFreeze,
|
|
|
|
marker2: marker::NoPod,
|
|
|
|
marker3: marker::NoShare,
|
|
|
|
value: Unsafe::new(value),
|
2013-11-21 23:30:34 -06:00
|
|
|
borrow: UNUSED,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Consumes the `RefCell`, returning the wrapped value.
|
|
|
|
pub fn unwrap(self) -> T {
|
|
|
|
assert!(self.borrow == UNUSED);
|
2014-03-10 16:55:37 -05:00
|
|
|
unsafe{self.value.unwrap()}
|
2013-11-21 23:30:34 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
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.
|
|
|
|
///
|
2013-12-14 23:26:09 -06:00
|
|
|
/// The borrow lasts until the returned `RefMut` exits scope. The value
|
2013-11-21 23:30:34 -06:00
|
|
|
/// 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.
|
|
|
|
///
|
2013-12-14 23:26:09 -06:00
|
|
|
/// The borrow lasts until the returned `RefMut` exits scope. The value
|
2013-11-21 23:30:34 -06:00
|
|
|
/// 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")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-11 16:54:27 -06:00
|
|
|
/// Sets the value, replacing what was there.
|
|
|
|
///
|
|
|
|
/// # Failure
|
|
|
|
///
|
|
|
|
/// Fails if the value is currently borrowed.
|
|
|
|
#[inline]
|
|
|
|
pub fn set(&self, value: T) {
|
|
|
|
let mut reference = self.borrow_mut();
|
2014-03-10 16:55:37 -05:00
|
|
|
*reference.get() = value;
|
2013-12-11 16:54:27 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T:Clone> RefCell<T> {
|
|
|
|
/// Returns a copy of the contained value.
|
|
|
|
///
|
|
|
|
/// # Failure
|
|
|
|
///
|
|
|
|
/// Fails if the value is currently mutably borrowed.
|
|
|
|
#[inline]
|
|
|
|
pub fn get(&self) -> T {
|
|
|
|
let reference = self.borrow();
|
|
|
|
(*reference.get()).clone()
|
|
|
|
}
|
2013-11-21 23:30:34 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: Clone> Clone for RefCell<T> {
|
|
|
|
fn clone(&self) -> RefCell<T> {
|
|
|
|
let x = self.borrow();
|
|
|
|
RefCell::new(x.get().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.
|
2013-12-11 19:04:50 -06:00
|
|
|
pub struct Ref<'b, T> {
|
|
|
|
priv parent: &'b RefCell<T>
|
2013-11-21 23:30:34 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#[unsafe_destructor]
|
2013-12-11 19:04:50 -06:00
|
|
|
impl<'b, T> Drop for Ref<'b, T> {
|
2013-11-21 23:30:34 -06:00
|
|
|
fn drop(&mut self) {
|
|
|
|
assert!(self.parent.borrow != WRITING && self.parent.borrow != UNUSED);
|
|
|
|
unsafe { self.parent.as_mut().borrow -= 1; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-11 19:04:50 -06:00
|
|
|
impl<'b, T> Ref<'b, T> {
|
2013-11-21 23:30:34 -06:00
|
|
|
/// Retrieve an immutable reference to the stored value.
|
|
|
|
#[inline]
|
|
|
|
pub fn get<'a>(&'a self) -> &'a T {
|
2014-03-10 16:55:37 -05:00
|
|
|
unsafe{ &*self.parent.value.get() }
|
2013-11-21 23:30:34 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-02-26 15:07:23 -06:00
|
|
|
impl<'b, T> Deref<T> for Ref<'b, T> {
|
|
|
|
#[inline]
|
|
|
|
fn deref<'a>(&'a self) -> &'a T {
|
2014-03-10 16:55:37 -05:00
|
|
|
unsafe{ &*self.parent.value.get() }
|
2014-02-26 15:07:23 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-21 23:30:34 -06:00
|
|
|
/// Wraps a mutable borrowed reference to a value in a `RefCell` box.
|
2013-12-11 19:04:50 -06:00
|
|
|
pub struct RefMut<'b, T> {
|
|
|
|
priv parent: &'b mut RefCell<T>
|
2013-11-21 23:30:34 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#[unsafe_destructor]
|
2013-12-11 19:04:50 -06:00
|
|
|
impl<'b, T> Drop for RefMut<'b, T> {
|
2013-11-21 23:30:34 -06:00
|
|
|
fn drop(&mut self) {
|
|
|
|
assert!(self.parent.borrow == WRITING);
|
|
|
|
self.parent.borrow = UNUSED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-11 19:04:50 -06:00
|
|
|
impl<'b, T> RefMut<'b, T> {
|
2013-11-21 23:30:34 -06:00
|
|
|
/// Retrieve a mutable reference to the stored value.
|
|
|
|
#[inline]
|
|
|
|
pub fn get<'a>(&'a mut self) -> &'a mut T {
|
2014-03-10 16:55:37 -05:00
|
|
|
unsafe{ &mut *self.parent.value.get() }
|
2013-11-21 23:30:34 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-02-26 15:07:23 -06:00
|
|
|
impl<'b, T> Deref<T> for RefMut<'b, T> {
|
|
|
|
#[inline]
|
|
|
|
fn deref<'a>(&'a self) -> &'a T {
|
2014-03-10 16:55:37 -05:00
|
|
|
unsafe{ &*self.parent.value.get() }
|
2014-02-26 15:07:23 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'b, T> DerefMut<T> for RefMut<'b, T> {
|
|
|
|
#[inline]
|
|
|
|
fn deref_mut<'a>(&'a mut self) -> &'a mut T {
|
2014-03-10 16:55:37 -05:00
|
|
|
unsafe{ &mut *self.parent.value.get() }
|
2014-02-26 15:07:23 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-21 23:30:34 -06:00
|
|
|
#[cfg(test)]
|
|
|
|
mod test {
|
|
|
|
use super::*;
|
|
|
|
|
2013-12-11 16:54:27 -06:00
|
|
|
#[test]
|
|
|
|
fn smoketest_cell() {
|
|
|
|
let x = Cell::new(10);
|
2014-02-24 19:38:40 -06:00
|
|
|
assert_eq!(x, Cell::new(10));
|
2013-12-11 16:54:27 -06:00
|
|
|
assert_eq!(x.get(), 10);
|
|
|
|
x.set(20);
|
2014-02-24 19:38:40 -06:00
|
|
|
assert_eq!(x, Cell::new(20));
|
2013-12-11 16:54:27 -06:00
|
|
|
assert_eq!(x.get(), 20);
|
|
|
|
|
|
|
|
let y = Cell::new((30, 40));
|
2014-02-24 19:38:40 -06:00
|
|
|
assert_eq!(y, Cell::new((30, 40)));
|
2013-12-11 16:54:27 -06:00
|
|
|
assert_eq!(y.get(), (30, 40));
|
|
|
|
}
|
|
|
|
|
2013-11-21 23:30:34 -06:00
|
|
|
#[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]
|
|
|
|
#[should_fail]
|
|
|
|
fn discard_doesnt_unborrow() {
|
|
|
|
let x = RefCell::new(0);
|
|
|
|
let _b = x.borrow();
|
|
|
|
let _ = _b;
|
|
|
|
let _b = x.borrow_mut();
|
|
|
|
}
|
|
|
|
}
|