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
17 use kinds::{marker, Pod};
18 use ops::{Deref, DerefMut, Drop};
19 use option::{None, Option, Some};
22 /// A mutable memory location that admits only `Pod` data.
24 priv value: Unsafe<T>,
25 priv marker1: marker::NoFreeze,
26 priv marker2: marker::NoShare,
30 /// Creates a new `Cell` containing the given value.
31 pub fn new(value: T) -> Cell<T> {
33 value: Unsafe::new(value),
34 marker1: marker::NoFreeze,
35 marker2: marker::NoShare,
39 /// Returns a copy of the contained value.
41 pub fn get(&self) -> T {
42 unsafe{ *self.value.get() }
45 /// Sets the contained value.
47 pub fn set(&self, value: T) {
49 *self.value.get() = value;
54 impl<T:Pod> Clone for Cell<T> {
55 fn clone(&self) -> Cell<T> {
60 impl<T:Eq + Pod> Eq for Cell<T> {
61 fn eq(&self, other: &Cell<T>) -> bool {
62 self.get() == other.get()
66 impl<T: fmt::Show> fmt::Show for Cell<T> {
67 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
68 write!(f.buf, r"Cell \{ value: {} \}", unsafe{*&self.value.get()})
72 /// A mutable memory location with dynamically checked borrow rules
73 pub struct RefCell<T> {
74 priv value: Unsafe<T>,
75 priv borrow: BorrowFlag,
76 priv marker1: marker::NoFreeze,
77 priv marker2: marker::NoPod,
78 priv marker3: marker::NoShare,
81 // Values [1, MAX-1] represent the number of `Ref` active
82 // (will not outgrow its range since `uint` is the size of the address space)
83 type BorrowFlag = uint;
84 static UNUSED: BorrowFlag = 0;
85 static WRITING: BorrowFlag = -1;
88 /// Create a new `RefCell` containing `value`
89 pub fn new(value: T) -> RefCell<T> {
91 marker1: marker::NoFreeze,
92 marker2: marker::NoPod,
93 marker3: marker::NoShare,
94 value: Unsafe::new(value),
99 /// Consumes the `RefCell`, returning the wrapped value.
100 pub fn unwrap(self) -> T {
101 assert!(self.borrow == UNUSED);
102 unsafe{self.value.unwrap()}
105 unsafe fn as_mut<'a>(&'a self) -> &'a mut RefCell<T> {
106 cast::transmute_mut(self)
109 /// Attempts to immutably borrow the wrapped value.
111 /// The borrow lasts until the returned `Ref` exits scope. Multiple
112 /// immutable borrows can be taken out at the same time.
114 /// Returns `None` if the value is currently mutably borrowed.
115 pub fn try_borrow<'a>(&'a self) -> Option<Ref<'a, T>> {
119 unsafe { self.as_mut().borrow += 1; }
120 Some(Ref { parent: self })
125 /// Immutably borrows the wrapped value.
127 /// The borrow lasts until the returned `Ref` exits scope. Multiple
128 /// immutable borrows can be taken out at the same time.
132 /// Fails if the value is currently mutably borrowed.
133 pub fn borrow<'a>(&'a self) -> Ref<'a, T> {
134 match self.try_borrow() {
136 None => fail!("RefCell<T> already mutably borrowed")
140 /// Mutably borrows the wrapped value.
142 /// The borrow lasts until the returned `RefMut` exits scope. The value
143 /// cannot be borrowed while this borrow is active.
145 /// Returns `None` if the value is currently borrowed.
146 pub fn try_borrow_mut<'a>(&'a self) -> Option<RefMut<'a, T>> {
149 let mut_self = self.as_mut();
150 mut_self.borrow = WRITING;
151 Some(RefMut { parent: mut_self })
157 /// Mutably borrows the wrapped value.
159 /// The borrow lasts until the returned `RefMut` exits scope. The value
160 /// cannot be borrowed while this borrow is active.
164 /// Fails if the value is currently borrowed.
165 pub fn borrow_mut<'a>(&'a self) -> RefMut<'a, T> {
166 match self.try_borrow_mut() {
168 None => fail!("RefCell<T> already borrowed")
172 /// Sets the value, replacing what was there.
176 /// Fails if the value is currently borrowed.
178 pub fn set(&self, value: T) {
179 let mut reference = self.borrow_mut();
180 *reference.get() = value;
184 impl<T:Clone> RefCell<T> {
185 /// Returns a copy of the contained value.
189 /// Fails if the value is currently mutably borrowed.
191 pub fn get(&self) -> T {
192 let reference = self.borrow();
193 (*reference.get()).clone()
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: Eq> Eq for RefCell<T> {
205 fn eq(&self, other: &RefCell<T>) -> bool {
206 let a = self.borrow();
207 let b = other.borrow();
212 /// Wraps a borrowed reference to a value in a `RefCell` box.
213 pub struct Ref<'b, T> {
214 priv parent: &'b RefCell<T>
218 impl<'b, T> Drop for Ref<'b, T> {
220 assert!(self.parent.borrow != WRITING && self.parent.borrow != UNUSED);
221 unsafe { self.parent.as_mut().borrow -= 1; }
225 impl<'b, T> Ref<'b, T> {
226 /// Retrieve an immutable reference to the stored value.
228 pub fn get<'a>(&'a self) -> &'a T {
229 unsafe{ &*self.parent.value.get() }
233 impl<'b, T> Deref<T> for Ref<'b, T> {
235 fn deref<'a>(&'a self) -> &'a T {
236 unsafe{ &*self.parent.value.get() }
240 /// Wraps a mutable borrowed reference to a value in a `RefCell` box.
241 pub struct RefMut<'b, T> {
242 priv parent: &'b mut RefCell<T>
246 impl<'b, T> Drop for RefMut<'b, T> {
248 assert!(self.parent.borrow == WRITING);
249 self.parent.borrow = UNUSED;
253 impl<'b, T> RefMut<'b, T> {
254 /// Retrieve a mutable reference to the stored value.
256 pub fn get<'a>(&'a mut self) -> &'a mut T {
257 unsafe{ &mut *self.parent.value.get() }
261 impl<'b, T> Deref<T> for RefMut<'b, T> {
263 fn deref<'a>(&'a self) -> &'a T {
264 unsafe{ &*self.parent.value.get() }
268 impl<'b, T> DerefMut<T> for RefMut<'b, T> {
270 fn deref_mut<'a>(&'a mut self) -> &'a mut T {
271 unsafe{ &mut *self.parent.value.get() }
280 fn smoketest_cell() {
281 let x = Cell::new(10);
282 assert_eq!(x, Cell::new(10));
283 assert_eq!(x.get(), 10);
285 assert_eq!(x, Cell::new(20));
286 assert_eq!(x.get(), 20);
288 let y = Cell::new((30, 40));
289 assert_eq!(y, Cell::new((30, 40)));
290 assert_eq!(y.get(), (30, 40));
294 fn double_imm_borrow() {
295 let x = RefCell::new(0);
296 let _b1 = x.borrow();
301 fn no_mut_then_imm_borrow() {
302 let x = RefCell::new(0);
303 let _b1 = x.borrow_mut();
304 assert!(x.try_borrow().is_none());
308 fn no_imm_then_borrow_mut() {
309 let x = RefCell::new(0);
310 let _b1 = x.borrow();
311 assert!(x.try_borrow_mut().is_none());
315 fn no_double_borrow_mut() {
316 let x = RefCell::new(0);
317 let _b1 = x.borrow_mut();
318 assert!(x.try_borrow_mut().is_none());
322 fn imm_release_borrow_mut() {
323 let x = RefCell::new(0);
325 let _b1 = x.borrow();
331 fn mut_release_borrow_mut() {
332 let x = RefCell::new(0);
334 let _b1 = x.borrow_mut();
340 fn double_borrow_single_release_no_borrow_mut() {
341 let x = RefCell::new(0);
342 let _b1 = x.borrow();
344 let _b2 = x.borrow();
346 assert!(x.try_borrow_mut().is_none());
351 fn discard_doesnt_unborrow() {
352 let x = RefCell::new(0);
355 let _b = x.borrow_mut();