(index<- )        ./libcore/cell.rs

    git branch:    * master           5200215 auto merge of #14035 : alexcrichton/rust/experimental, r=huonw
    modified:    Fri May  9 13:02:28 2014
   1  // Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
   2  // file at the top-level directory of this distribution and at
   3  // http://rust-lang.org/COPYRIGHT.
   4  //
   5  // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
   6  // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
   7  // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
   8  // option. This file may not be copied, modified, or distributed
   9  // except according to those terms.
  10  
  11  //! Types that provide interior mutability.
  12  
  13  use clone::Clone;
  14  use cmp::Eq;
  15  use kinds::{marker, Copy};
  16  use ops::{Deref, DerefMut, Drop};
  17  use option::{None, Option, Some};
  18  use ty::Unsafe;
  19  
  20  /// A mutable memory location that admits only `Copy` data.
  21  pub struct Cell<T> {
  22      value: Unsafe<T>,
  23      noshare: marker::NoShare,
  24  }
  25  
  26  impl<T:Copy> Cell<T> {
  27      /// Creates a new `Cell` containing the given value.
  28      pub fn new(valueT) -> Cell<T> {
  29          Cell {
  30              value: Unsafe::new(value),
  31              noshare: marker::NoShare,
  32          }
  33      }
  34  
  35      /// Returns a copy of the contained value.
  36      #[inline]
  37      pub fn get(&self) -> T {
  38          unsafe{ *self.value.get() }
  39      }
  40  
  41      /// Sets the contained value.
  42      #[inline]
  43      pub fn set(&self, valueT) {
  44          unsafe {
  45              *self.value.get() = value;
  46          }
  47      }
  48  }
  49  
  50  impl<T:Copy> Clone for Cell<T> {
  51      fn clone(&self) -> Cell<T> {
  52          Cell::new(self.get())
  53      }
  54  }
  55  
  56  impl<T:Eq + Copy> Eq for Cell<T> {
  57      fn eq(&self, other&Cell<T>) -> bool {
  58          self.get() == other.get()
  59      }
  60  }
  61  
  62  /// A mutable memory location with dynamically checked borrow rules
  63  pub struct RefCell<T> {
  64      value: Unsafe<T>,
  65      borrow: Cell<BorrowFlag>,
  66      nocopy: marker::NoCopy,
  67      noshare: marker::NoShare,
  68  }
  69  
  70  // Values [1, MAX-1] represent the number of `Ref` active
  71  // (will not outgrow its range since `uint` is the size of the address space)
  72  type BorrowFlag = uint;
  73  static UNUSED: BorrowFlag = 0;
  74  static WRITING: BorrowFlag = -1;
  75  
  76  impl<T> RefCell<T> {
  77      /// Create a new `RefCell` containing `value`
  78      pub fn new(valueT) -> RefCell<T> {
  79          RefCell {
  80              value: Unsafe::new(value),
  81              borrow: Cell::new(UNUSED),
  82              nocopy: marker::NoCopy,
  83              noshare: marker::NoShare,
  84          }
  85      }
  86  
  87      /// Consumes the `RefCell`, returning the wrapped value.
  88      pub fn unwrap(self) -> T {
  89          debug_assert!(self.borrow.get() == UNUSED);
  90          unsafe{self.value.unwrap()}
  91      }
  92  
  93      /// Attempts to immutably borrow the wrapped value.
  94      ///
  95      /// The borrow lasts until the returned `Ref` exits scope. Multiple
  96      /// immutable borrows can be taken out at the same time.
  97      ///
  98      /// Returns `None` if the value is currently mutably borrowed.
  99      pub fn try_borrow<'a>(&'a self) -> Option<Ref<'a, T>> {
 100          match self.borrow.get() {
 101              WRITING => None,
 102              borrow => {
 103                  self.borrow.set(borrow + 1);
 104                  Some(Ref { parent: self })
 105              }
 106          }
 107      }
 108  
 109      /// Immutably borrows the wrapped value.
 110      ///
 111      /// The borrow lasts until the returned `Ref` exits scope. Multiple
 112      /// immutable borrows can be taken out at the same time.
 113      ///
 114      /// # Failure
 115      ///
 116      /// Fails if the value is currently mutably borrowed.
 117      pub fn borrow<'a>(&'a self) -> Ref<'a, T> {
 118          match self.try_borrow() {
 119              Some(ptr) => ptr,
 120              None => fail!("RefCell<T> already mutably borrowed")
 121          }
 122      }
 123  
 124      /// Mutably borrows the wrapped value.
 125      ///
 126      /// The borrow lasts until the returned `RefMut` exits scope. The value
 127      /// cannot be borrowed while this borrow is active.
 128      ///
 129      /// Returns `None` if the value is currently borrowed.
 130      pub fn try_borrow_mut<'a>(&'a self) -> Option<RefMut<'a, T>> {
 131          match self.borrow.get() {
 132              UNUSED => {
 133                  self.borrow.set(WRITING);
 134                  Some(RefMut { parent: self })
 135              },
 136              _ => None
 137          }
 138      }
 139  
 140      /// Mutably borrows the wrapped value.
 141      ///
 142      /// The borrow lasts until the returned `RefMut` exits scope. The value
 143      /// cannot be borrowed while this borrow is active.
 144      ///
 145      /// # Failure
 146      ///
 147      /// Fails if the value is currently borrowed.
 148      pub fn borrow_mut<'a>(&'a self) -> RefMut<'a, T> {
 149          match self.try_borrow_mut() {
 150              Some(ptr) => ptr,
 151              None => fail!("RefCell<T> already borrowed")
 152          }
 153      }
 154  }
 155  
 156  impl<T: Clone> Clone for RefCell<T> {
 157      fn clone(&self) -> RefCell<T> {
 158          RefCell::new(self.borrow().clone())
 159      }
 160  }
 161  
 162  impl<T: Eq> Eq for RefCell<T> {
 163      fn eq(&self, other&RefCell<T>) -> bool {
 164          *self.borrow() == *other.borrow()
 165      }
 166  }
 167  
 168  /// Wraps a borrowed reference to a value in a `RefCell` box.
 169  pub struct Ref<'b, T> {
 170      parent: &'b RefCell<T>
 171  }
 172  
 173  #[unsafe_destructor]
 174  impl<'b, T> Drop for Ref<'b, T> {
 175      fn drop(&mut self) {
 176          let borrow = self.parent.borrow.get();
 177          debug_assert!(borrow != WRITING && borrow != UNUSED);
 178          self.parent.borrow.set(borrow - 1);
 179      }
 180  }
 181  
 182  impl<'b, T> Deref<T> for Ref<'b, T> {
 183      #[inline]
 184      fn deref<'a>(&'a self) -> &'a T {
 185          unsafe { &*self.parent.value.get() }
 186      }
 187  }
 188  
 189  /// Wraps a mutable borrowed reference to a value in a `RefCell` box.
 190  pub struct RefMut<'b, T> {
 191      parent: &'b RefCell<T>
 192  }
 193  
 194  #[unsafe_destructor]
 195  impl<'b, T> Drop for RefMut<'b, T> {
 196      fn drop(&mut self) {
 197          let borrow = self.parent.borrow.get();
 198          debug_assert!(borrow == WRITING);
 199          self.parent.borrow.set(UNUSED);
 200      }
 201  }
 202  
 203  impl<'b, T> Deref<T> for RefMut<'b, T> {
 204      #[inline]
 205      fn deref<'a>(&'a self) -> &'a T {
 206          unsafe { &*self.parent.value.get() }
 207      }
 208  }
 209  
 210  impl<'b, T> DerefMut<T> for RefMut<'b, T> {
 211      #[inline]
 212      fn deref_mut<'a>(&'a mut self) -> &'a mut T {
 213          unsafe { &mut *self.parent.value.get() }
 214      }
 215  }
 216  
 217  #[cfg(test)]
 218  mod test {
 219      use super::*;
 220  
 221      #[test]
 222      fn smoketest_cell() {
 223          let x = Cell::new(10);
 224          assert!(x == Cell::new(10));
 225          assert!(x.get() == 10);
 226          x.set(20);
 227          assert!(x == Cell::new(20));
 228          assert!(x.get() == 20);
 229  
 230          let y = Cell::new((30, 40));
 231          assert!(y == Cell::new((30, 40)));
 232          assert!(y.get() == (30, 40));
 233      }
 234  
 235      #[test]
 236      fn cell_has_sensible_show() {
 237          use str::StrSlice;
 238  
 239          let x = ::realcore::cell::Cell::new("foo bar");
 240          assert!(format!("{}", x).contains(x.get()));
 241  
 242          x.set("baz qux");
 243          assert!(format!("{}", x).contains(x.get()));
 244      }
 245  
 246      #[test]
 247      fn double_imm_borrow() {
 248          let x = RefCell::new(0);
 249          let _b1 = x.borrow();
 250          x.borrow();
 251      }
 252  
 253      #[test]
 254      fn no_mut_then_imm_borrow() {
 255          let x = RefCell::new(0);
 256          let _b1 = x.borrow_mut();
 257          assert!(x.try_borrow().is_none());
 258      }
 259  
 260      #[test]
 261      fn no_imm_then_borrow_mut() {
 262          let x = RefCell::new(0);
 263          let _b1 = x.borrow();
 264          assert!(x.try_borrow_mut().is_none());
 265      }
 266  
 267      #[test]
 268      fn no_double_borrow_mut() {
 269          let x = RefCell::new(0);
 270          let _b1 = x.borrow_mut();
 271          assert!(x.try_borrow_mut().is_none());
 272      }
 273  
 274      #[test]
 275      fn imm_release_borrow_mut() {
 276          let x = RefCell::new(0);
 277          {
 278              let _b1 = x.borrow();
 279          }
 280          x.borrow_mut();
 281      }
 282  
 283      #[test]
 284      fn mut_release_borrow_mut() {
 285          let x = RefCell::new(0);
 286          {
 287              let _b1 = x.borrow_mut();
 288          }
 289          x.borrow();
 290      }
 291  
 292      #[test]
 293      fn double_borrow_single_release_no_borrow_mut() {
 294          let x = RefCell::new(0);
 295          let _b1 = x.borrow();
 296          {
 297              let _b2 = x.borrow();
 298          }
 299          assert!(x.try_borrow_mut().is_none());
 300      }
 301  
 302      #[test]
 303      #[should_fail]
 304      fn discard_doesnt_unborrow() {
 305          let x = RefCell::new(0);
 306          let _b = x.borrow();
 307          let _ = _b;
 308          let _b = x.borrow_mut();
 309      }
 310  }


libcore/cell.rs:20:60-20:60 -struct- definition:
/// A mutable memory location that admits only `Copy` data.
pub struct Cell<T> {
    value: Unsafe<T>,
references:- 8
28:     pub fn new(value: T) -> Cell<T> {
29:         Cell {
30:             value: Unsafe::new(value),
--
56: impl<T:Eq + Copy> Eq for Cell<T> {
57:     fn eq(&self, other: &Cell<T>) -> bool {
58:         self.get() == other.get()
--
64:     value: Unsafe<T>,
65:     borrow: Cell<BorrowFlag>,
66:     nocopy: marker::NoCopy,


libcore/cell.rs:71:78-71:78 -NK_AS_STR_TODO- definition:
// (will not outgrow its range since `uint` is the size of the address space)
type BorrowFlag = uint;
static UNUSED: BorrowFlag = 0;
references:- 3
73: static UNUSED: BorrowFlag = 0;
74: static WRITING: BorrowFlag = -1;


libcore/cell.rs:62:68-62:68 -struct- definition:
/// A mutable memory location with dynamically checked borrow rules
pub struct RefCell<T> {
    value: Unsafe<T>,
references:- 9
78:     pub fn new(value: T) -> RefCell<T> {
79:         RefCell {
80:             value: Unsafe::new(value),
--
156: impl<T: Clone> Clone for RefCell<T> {
157:     fn clone(&self) -> RefCell<T> {
158:         RefCell::new(self.borrow().clone())
--
190: pub struct RefMut<'b, T> {
191:     parent: &'b RefCell<T>
192: }


libcore/cell.rs:189:70-189:70 -struct- definition:
/// Wraps a mutable borrowed reference to a value in a `RefCell` box.
pub struct RefMut<'b, T> {
    parent: &'b RefCell<T>
references:- 6
133:                 self.borrow.set(WRITING);
134:                 Some(RefMut { parent: self })
135:             },
--
210: impl<'b, T> DerefMut<T> for RefMut<'b, T> {
211:     #[inline]


libcore/cell.rs:168:62-168:62 -struct- definition:
/// Wraps a borrowed reference to a value in a `RefCell` box.
pub struct Ref<'b, T> {
    parent: &'b RefCell<T>
references:- 5
103:                 self.borrow.set(borrow + 1);
104:                 Some(Ref { parent: self })
105:             }
--
174: impl<'b, T> Drop for Ref<'b, T> {
175:     fn drop(&mut self) {
--
182: impl<'b, T> Deref<T> for Ref<'b, T> {
183:     #[inline]