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

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


libstd/cell.rs:69:68-69:68 -struct- definition:
/// A mutable memory location with dynamically checked borrow rules
pub struct RefCell<T> {
    value: Unsafe<T>,
references:- 9
169: impl<T: Eq> Eq for RefCell<T> {
170:     fn eq(&self, other: &RefCell<T>) -> bool {
171:         *self.borrow() == *other.borrow()
--
176: pub struct Ref<'b, T> {
177:     parent: &'b RefCell<T>
178: }
--
197: pub struct RefMut<'b, T> {
198:     parent: &'b RefCell<T>
199: }


libstd/cell.rs:175:62-175: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
181: impl<'b, T> Drop for Ref<'b, T> {
182:     fn drop(&mut self) {
--
189: impl<'b, T> Deref<T> for Ref<'b, T> {
190:     #[inline]


libstd/cell.rs:21:60-21:60 -struct- definition:
/// A mutable memory location that admits only `Copy` data.
pub struct Cell<T> {
    value: Unsafe<T>,
references:- 14
29:     pub fn new(value: T) -> Cell<T> {
30:         Cell {
31:             value: Unsafe::new(value),
--
57: impl<T:Eq + Copy> Eq for Cell<T> {
58:     fn eq(&self, other: &Cell<T>) -> bool {
59:         self.get() == other.get()
--
63: impl<T: Copy + fmt::Show> fmt::Show for Cell<T> {
64:     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
--
71:     value: Unsafe<T>,
72:     borrow: Cell<BorrowFlag>,
73:     nocopy: marker::NoCopy,
libstd/comm/mod.rs:
344:     inner: Flavor<T>,
345:     sends: Cell<uint>,
346:     // can't share in an arc
libstd/rc.rs:
39:     strong: Cell<uint>,
40:     weak: Cell<uint>
41: }
libstd/comm/select.rs:
66:     tail: *mut Handle<'static, ()>,
67:     next_id: Cell<uint>,
68:     marker1: marker::NoSend,


libstd/cell.rs:78:78-78:78 -ty- definition:
// (will not outgrow its range since `uint` is the size of the address space)
type BorrowFlag = uint;
static UNUSED: BorrowFlag = 0;
references:- 3
79: type BorrowFlag = uint;
80: static UNUSED: BorrowFlag = 0;
81: static WRITING: BorrowFlag = -1;


libstd/cell.rs:196:70-196: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
210: impl<'b, T> Deref<T> for RefMut<'b, T> {
211:     #[inline]
--
217: impl<'b, T> DerefMut<T> for RefMut<'b, T> {
218:     #[inline]