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.
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.
11 //! Types dealing with dynamic mutability
15 use util::NonCopyable;
19 A dynamic, mutable location.
21 Similar to a mutable option type, but friendlier.
25 #[deriving(Clone, DeepClone, Eq)]
32 /// Creates a new full cell with the given value.
33 pub fn new(value: T) -> Cell<T> {
34 Cell { value: Some(value) }
37 /// Yields the value, failing if the cell is empty.
38 pub fn take(&self) -> T {
39 let this = unsafe { cast::transmute_mut(self) };
41 fail!("attempt to take an empty cell");
44 this.value.take_unwrap()
47 /// Yields the value if the cell is full, or `None` if it is empty.
48 pub fn take_opt(&self) -> Option<T> {
49 let this = unsafe { cast::transmute_mut(self) };
53 /// Returns true if the cell is empty and false if the cell is full.
54 pub fn is_empty(&self) -> bool {
61 let value_cell = Cell::new(~10);
62 assert!(!value_cell.is_empty());
63 let value = value_cell.take();
64 assert!(value == ~10);
65 assert!(value_cell.is_empty());
70 fn test_take_empty() {
71 let value_cell: Cell<~int> = Cell::new(~0);
77 /// A mutable memory location with dynamically checked borrow rules
79 pub struct RefCell<T> {
81 priv borrow: BorrowFlag,
85 // Values [1, MAX-1] represent the number of `Ref` active
86 // (will not outgrow its range since `uint` is the size of the address space)
87 type BorrowFlag = uint;
88 static UNUSED: BorrowFlag = 0;
89 static WRITING: BorrowFlag = -1;
92 /// Create a new `RefCell` containing `value`
93 pub fn new(value: T) -> RefCell<T> {
101 /// Consumes the `RefCell`, returning the wrapped value.
102 pub fn unwrap(self) -> T {
103 assert!(self.borrow == UNUSED);
107 unsafe fn as_mut<'a>(&'a self) -> &'a mut RefCell<T> {
108 cast::transmute_mut(self)
111 /// Attempts to immutably borrow the wrapped value.
113 /// The borrow lasts until the returned `Ref` exits scope. Multiple
114 /// immutable borrows can be taken out at the same time.
116 /// Returns `None` if the value is currently mutably borrowed.
117 pub fn try_borrow<'a>(&'a self) -> Option<Ref<'a, T>> {
121 unsafe { self.as_mut().borrow += 1; }
122 Some(Ref { parent: self })
127 /// Immutably borrows the wrapped value.
129 /// The borrow lasts until the returned `Ref` exits scope. Multiple
130 /// immutable borrows can be taken out at the same time.
134 /// Fails if the value is currently mutably borrowed.
135 pub fn borrow<'a>(&'a self) -> Ref<'a, T> {
136 match self.try_borrow() {
138 None => fail!("RefCell<T> already mutably borrowed")
142 /// Mutably borrows the wrapped value.
144 /// The borrow lasts untile the returned `RefMut` exits scope. The value
145 /// cannot be borrowed while this borrow is active.
147 /// Returns `None` if the value is currently borrowed.
148 pub fn try_borrow_mut<'a>(&'a self) -> Option<RefMut<'a, T>> {
151 let mut_self = self.as_mut();
152 mut_self.borrow = WRITING;
153 Some(RefMut { parent: mut_self })
159 /// Mutably borrows the wrapped value.
161 /// The borrow lasts untile the returned `RefMut` exits scope. The value
162 /// cannot be borrowed while this borrow is active.
166 /// Fails if the value is currently borrowed.
167 pub fn borrow_mut<'a>(&'a self) -> RefMut<'a, T> {
168 match self.try_borrow_mut() {
170 None => fail!("RefCell<T> already borrowed")
174 /// Immutably borrows the wrapped value and applies `blk` to it.
178 /// Fails if the value is currently mutably borrowed.
180 pub fn with<U>(&self, blk: |&T| -> U) -> U {
181 let ptr = self.borrow();
185 /// Mutably borrows the wrapped value and applies `blk` to it.
189 /// Fails if the value is currently borrowed.
191 pub fn with_mut<U>(&self, blk: |&mut T| -> U) -> U {
192 let mut ptr = self.borrow_mut();
197 impl<T: Clone> Clone for RefCell<T> {
198 fn clone(&self) -> RefCell<T> {
199 let x = self.borrow();
200 RefCell::new(x.get().clone())
204 impl<T: DeepClone> DeepClone for RefCell<T> {
205 fn deep_clone(&self) -> RefCell<T> {
206 let x = self.borrow();
207 RefCell::new(x.get().deep_clone())
211 impl<T: Eq> Eq for RefCell<T> {
212 fn eq(&self, other: &RefCell<T>) -> bool {
213 let a = self.borrow();
214 let b = other.borrow();
219 /// Wraps a borrowed reference to a value in a `RefCell` box.
220 pub struct Ref<'box, T> {
221 priv parent: &'box RefCell<T>
225 impl<'box, T> Drop for Ref<'box, T> {
227 assert!(self.parent.borrow != WRITING && self.parent.borrow != UNUSED);
228 unsafe { self.parent.as_mut().borrow -= 1; }
232 impl<'box, T> Ref<'box, T> {
233 /// Retrieve an immutable reference to the stored value.
235 pub fn get<'a>(&'a self) -> &'a T {
240 /// Wraps a mutable borrowed reference to a value in a `RefCell` box.
241 pub struct RefMut<'box, T> {
242 priv parent: &'box mut RefCell<T>
246 impl<'box, T> Drop for RefMut<'box, T> {
248 assert!(self.parent.borrow == WRITING);
249 self.parent.borrow = UNUSED;
253 impl<'box, T> RefMut<'box, T> {
254 /// Retrieve a mutable reference to the stored value.
256 pub fn get<'a>(&'a mut self) -> &'a mut T {
257 &mut self.parent.value
266 fn double_imm_borrow() {
267 let x = RefCell::new(0);
268 let _b1 = x.borrow();
273 fn no_mut_then_imm_borrow() {
274 let x = RefCell::new(0);
275 let _b1 = x.borrow_mut();
276 assert!(x.try_borrow().is_none());
280 fn no_imm_then_borrow_mut() {
281 let x = RefCell::new(0);
282 let _b1 = x.borrow();
283 assert!(x.try_borrow_mut().is_none());
287 fn no_double_borrow_mut() {
288 let x = RefCell::new(0);
289 let _b1 = x.borrow_mut();
290 assert!(x.try_borrow_mut().is_none());
294 fn imm_release_borrow_mut() {
295 let x = RefCell::new(0);
297 let _b1 = x.borrow();
303 fn mut_release_borrow_mut() {
304 let x = RefCell::new(0);
306 let _b1 = x.borrow_mut();
312 fn double_borrow_single_release_no_borrow_mut() {
313 let x = RefCell::new(0);
314 let _b1 = x.borrow();
316 let _b2 = x.borrow();
318 assert!(x.try_borrow_mut().is_none());
323 let x = RefCell::new(0);
324 assert_eq!(1, x.with(|x| *x+1));
329 fn mut_borrow_with() {
330 let x = RefCell::new(0);
331 let _b1 = x.borrow_mut();
337 let x = RefCell::new(0);
338 let _b1 = x.borrow();
339 assert_eq!(1, x.with(|x| *x+1));
344 let x = RefCell::new(0);
345 x.with_mut(|x| *x += 1);
347 assert_eq!(1, *b.get());
352 fn borrow_with_mut() {
353 let x = RefCell::new(0);
355 x.with_mut(|x| *x += 1);
360 fn discard_doesnt_unborrow() {
361 let x = RefCell::new(0);
364 let _b = x.borrow_mut();