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;
18 use unstable::intrinsics;
20 /// A mutable memory location that admits only `Pod` data.
27 // NB: For `stage0`, we omit the `Pod` bound. This is unsound but will help
28 // us get started on removing `@mut` from `rustc`.
32 /// Creates a new `Cell` containing the given value.
33 pub fn new(value: T) -> Cell<T> {
39 /// Returns a copy of the contained value.
41 pub fn get(&self) -> T {
43 let mut result = intrinsics::uninit();
44 intrinsics::copy_nonoverlapping_memory(&mut result, &self.value, 1);
49 /// Sets the contained value.
51 pub fn set(&self, value: T) {
53 intrinsics::copy_nonoverlapping_memory(cast::transmute_mut(&self.value), &value, 1)
59 impl<T: ::kinds::Pod> Cell<T> {
60 /// Creates a new `Cell` containing the given value.
61 pub fn new(value: T) -> Cell<T> {
67 /// Returns a copy of the contained value.
69 pub fn get(&self) -> T {
73 /// Sets the contained value.
75 pub fn set(&self, value: T) {
77 *cast::transmute_mut(&self.value) = value
82 /// A mutable memory location with dynamically checked borrow rules
84 pub struct RefCell<T> {
86 priv borrow: BorrowFlag,
90 // Values [1, MAX-1] represent the number of `Ref` active
91 // (will not outgrow its range since `uint` is the size of the address space)
92 type BorrowFlag = uint;
93 static UNUSED: BorrowFlag = 0;
94 static WRITING: BorrowFlag = -1;
97 /// Create a new `RefCell` containing `value`
98 pub fn new(value: T) -> RefCell<T> {
106 /// Consumes the `RefCell`, returning the wrapped value.
107 pub fn unwrap(self) -> T {
108 assert!(self.borrow == UNUSED);
112 unsafe fn as_mut<'a>(&'a self) -> &'a mut RefCell<T> {
113 cast::transmute_mut(self)
116 /// Attempts to immutably borrow the wrapped value.
118 /// The borrow lasts until the returned `Ref` exits scope. Multiple
119 /// immutable borrows can be taken out at the same time.
121 /// Returns `None` if the value is currently mutably borrowed.
122 pub fn try_borrow<'a>(&'a self) -> Option<Ref<'a, T>> {
126 unsafe { self.as_mut().borrow += 1; }
127 Some(Ref { parent: self })
132 /// Immutably borrows the wrapped value.
134 /// The borrow lasts until the returned `Ref` exits scope. Multiple
135 /// immutable borrows can be taken out at the same time.
139 /// Fails if the value is currently mutably borrowed.
140 pub fn borrow<'a>(&'a self) -> Ref<'a, T> {
141 match self.try_borrow() {
143 None => fail!("RefCell<T> already mutably borrowed")
147 /// Mutably borrows the wrapped value.
149 /// The borrow lasts until the returned `RefMut` exits scope. The value
150 /// cannot be borrowed while this borrow is active.
152 /// Returns `None` if the value is currently borrowed.
153 pub fn try_borrow_mut<'a>(&'a self) -> Option<RefMut<'a, T>> {
156 let mut_self = self.as_mut();
157 mut_self.borrow = WRITING;
158 Some(RefMut { parent: mut_self })
164 /// Mutably borrows the wrapped value.
166 /// The borrow lasts until the returned `RefMut` exits scope. The value
167 /// cannot be borrowed while this borrow is active.
171 /// Fails if the value is currently borrowed.
172 pub fn borrow_mut<'a>(&'a self) -> RefMut<'a, T> {
173 match self.try_borrow_mut() {
175 None => fail!("RefCell<T> already borrowed")
179 /// Immutably borrows the wrapped value and applies `blk` to it.
183 /// Fails if the value is currently mutably borrowed.
185 pub fn with<U>(&self, blk: |&T| -> U) -> U {
186 let ptr = self.borrow();
190 /// Mutably borrows the wrapped value and applies `blk` to it.
194 /// Fails if the value is currently borrowed.
196 pub fn with_mut<U>(&self, blk: |&mut T| -> U) -> U {
197 let mut ptr = self.borrow_mut();
201 /// Sets the value, replacing what was there.
205 /// Fails if the value is currently borrowed.
207 pub fn set(&self, value: T) {
208 let mut reference = self.borrow_mut();
209 *reference.get() = value
213 impl<T:Clone> RefCell<T> {
214 /// Returns a copy of the contained value.
218 /// Fails if the value is currently mutably borrowed.
220 pub fn get(&self) -> T {
221 let reference = self.borrow();
222 (*reference.get()).clone()
226 impl<T: Clone> Clone for RefCell<T> {
227 fn clone(&self) -> RefCell<T> {
228 let x = self.borrow();
229 RefCell::new(x.get().clone())
233 impl<T: DeepClone> DeepClone for RefCell<T> {
234 fn deep_clone(&self) -> RefCell<T> {
235 let x = self.borrow();
236 RefCell::new(x.get().deep_clone())
240 impl<T: Eq> Eq for RefCell<T> {
241 fn eq(&self, other: &RefCell<T>) -> bool {
242 let a = self.borrow();
243 let b = other.borrow();
248 /// Wraps a borrowed reference to a value in a `RefCell` box.
249 pub struct Ref<'b, T> {
250 priv parent: &'b RefCell<T>
254 impl<'b, T> Drop for Ref<'b, T> {
256 assert!(self.parent.borrow != WRITING && self.parent.borrow != UNUSED);
257 unsafe { self.parent.as_mut().borrow -= 1; }
261 impl<'b, T> Ref<'b, T> {
262 /// Retrieve an immutable reference to the stored value.
264 pub fn get<'a>(&'a self) -> &'a T {
269 /// Wraps a mutable borrowed reference to a value in a `RefCell` box.
270 pub struct RefMut<'b, T> {
271 priv parent: &'b mut RefCell<T>
275 impl<'b, T> Drop for RefMut<'b, T> {
277 assert!(self.parent.borrow == WRITING);
278 self.parent.borrow = UNUSED;
282 impl<'b, T> RefMut<'b, T> {
283 /// Retrieve a mutable reference to the stored value.
285 pub fn get<'a>(&'a mut self) -> &'a mut T {
286 &mut self.parent.value
295 fn smoketest_cell() {
296 let x = Cell::new(10);
297 assert_eq!(x.get(), 10);
299 assert_eq!(x.get(), 20);
301 let y = Cell::new((30, 40));
302 assert_eq!(y.get(), (30, 40));
306 fn double_imm_borrow() {
307 let x = RefCell::new(0);
308 let _b1 = x.borrow();
313 fn no_mut_then_imm_borrow() {
314 let x = RefCell::new(0);
315 let _b1 = x.borrow_mut();
316 assert!(x.try_borrow().is_none());
320 fn no_imm_then_borrow_mut() {
321 let x = RefCell::new(0);
322 let _b1 = x.borrow();
323 assert!(x.try_borrow_mut().is_none());
327 fn no_double_borrow_mut() {
328 let x = RefCell::new(0);
329 let _b1 = x.borrow_mut();
330 assert!(x.try_borrow_mut().is_none());
334 fn imm_release_borrow_mut() {
335 let x = RefCell::new(0);
337 let _b1 = x.borrow();
343 fn mut_release_borrow_mut() {
344 let x = RefCell::new(0);
346 let _b1 = x.borrow_mut();
352 fn double_borrow_single_release_no_borrow_mut() {
353 let x = RefCell::new(0);
354 let _b1 = x.borrow();
356 let _b2 = x.borrow();
358 assert!(x.try_borrow_mut().is_none());
363 let x = RefCell::new(0);
364 assert_eq!(1, x.with(|x| *x+1));
369 fn mut_borrow_with() {
370 let x = RefCell::new(0);
371 let _b1 = x.borrow_mut();
377 let x = RefCell::new(0);
378 let _b1 = x.borrow();
379 assert_eq!(1, x.with(|x| *x+1));
384 let x = RefCell::new(0);
385 x.with_mut(|x| *x += 1);
387 assert_eq!(1, *b.get());
392 fn borrow_with_mut() {
393 let x = RefCell::new(0);
395 x.with_mut(|x| *x += 1);
400 fn discard_doesnt_unborrow() {
401 let x = RefCell::new(0);
404 let _b = x.borrow_mut();