]> git.lizzy.rs Git - rust.git/blob - src/libstd/cell.rs
auto merge of #10977 : brson/rust/androidtest, r=brson
[rust.git] / src / libstd / cell.rs
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 prelude::*;
14 use cast;
15 use util::NonCopyable;
16
17 #[cfg(stage0)]
18 use unstable::intrinsics;
19
20 /// A mutable memory location that admits only `Pod` data.
21 #[no_freeze]
22 #[deriving(Clone)]
23 pub struct Cell<T> {
24     priv value: T,
25 }
26
27 // NB: For `stage0`, we omit the `Pod` bound. This is unsound but will help
28 // us get started on removing `@mut` from `rustc`.
29
30 #[cfg(stage0)]
31 impl<T> Cell<T> {
32     /// Creates a new `Cell` containing the given value.
33     pub fn new(value: T) -> Cell<T> {
34         Cell {
35             value: value,
36         }
37     }
38
39     /// Returns a copy of the contained value.
40     #[inline]
41     pub fn get(&self) -> T {
42         unsafe {
43             let mut result = intrinsics::uninit();
44             intrinsics::copy_nonoverlapping_memory(&mut result, &self.value, 1);
45             result
46         }
47     }
48
49     /// Sets the contained value.
50     #[inline]
51     pub fn set(&self, value: T) {
52         unsafe {
53             intrinsics::copy_nonoverlapping_memory(cast::transmute_mut(&self.value), &value, 1)
54         }
55     }
56 }
57
58 #[cfg(not(stage0))]
59 impl<T: ::kinds::Pod> Cell<T> {
60     /// Creates a new `Cell` containing the given value.
61     pub fn new(value: T) -> Cell<T> {
62         Cell {
63             value: value,
64         }
65     }
66
67     /// Returns a copy of the contained value.
68     #[inline]
69     pub fn get(&self) -> T {
70         self.value
71     }
72
73     /// Sets the contained value.
74     #[inline]
75     pub fn set(&self, value: T) {
76         unsafe {
77             *cast::transmute_mut(&self.value) = value
78         }
79     }
80 }
81
82 /// A mutable memory location with dynamically checked borrow rules
83 #[no_freeze]
84 pub struct RefCell<T> {
85     priv value: T,
86     priv borrow: BorrowFlag,
87     priv nc: NonCopyable
88 }
89
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;
95
96 impl<T> RefCell<T> {
97     /// Create a new `RefCell` containing `value`
98     pub fn new(value: T) -> RefCell<T> {
99         RefCell {
100             value: value,
101             borrow: UNUSED,
102             nc: NonCopyable
103         }
104     }
105
106     /// Consumes the `RefCell`, returning the wrapped value.
107     pub fn unwrap(self) -> T {
108         assert!(self.borrow == UNUSED);
109         self.value
110     }
111
112     unsafe fn as_mut<'a>(&'a self) -> &'a mut RefCell<T> {
113         cast::transmute_mut(self)
114     }
115
116     /// Attempts to immutably borrow 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     /// Returns `None` if the value is currently mutably borrowed.
122     pub fn try_borrow<'a>(&'a self) -> Option<Ref<'a, T>> {
123         match self.borrow {
124             WRITING => None,
125             _ => {
126                 unsafe { self.as_mut().borrow += 1; }
127                 Some(Ref { parent: self })
128             }
129         }
130     }
131
132     /// Immutably borrows the wrapped value.
133     ///
134     /// The borrow lasts until the returned `Ref` exits scope. Multiple
135     /// immutable borrows can be taken out at the same time.
136     ///
137     /// # Failure
138     ///
139     /// Fails if the value is currently mutably borrowed.
140     pub fn borrow<'a>(&'a self) -> Ref<'a, T> {
141         match self.try_borrow() {
142             Some(ptr) => ptr,
143             None => fail!("RefCell<T> already mutably borrowed")
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     /// Returns `None` if the value is currently borrowed.
153     pub fn try_borrow_mut<'a>(&'a self) -> Option<RefMut<'a, T>> {
154         match self.borrow {
155             UNUSED => unsafe {
156                 let mut_self = self.as_mut();
157                 mut_self.borrow = WRITING;
158                 Some(RefMut { parent: mut_self })
159             },
160             _ => None
161         }
162     }
163
164     /// Mutably borrows the wrapped value.
165     ///
166     /// The borrow lasts until the returned `RefMut` exits scope. The value
167     /// cannot be borrowed while this borrow is active.
168     ///
169     /// # Failure
170     ///
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() {
174             Some(ptr) => ptr,
175             None => fail!("RefCell<T> already borrowed")
176         }
177     }
178
179     /// Immutably borrows the wrapped value and applies `blk` to it.
180     ///
181     /// # Failure
182     ///
183     /// Fails if the value is currently mutably borrowed.
184     #[inline]
185     pub fn with<U>(&self, blk: |&T| -> U) -> U {
186         let ptr = self.borrow();
187         blk(ptr.get())
188     }
189
190     /// Mutably borrows the wrapped value and applies `blk` to it.
191     ///
192     /// # Failure
193     ///
194     /// Fails if the value is currently borrowed.
195     #[inline]
196     pub fn with_mut<U>(&self, blk: |&mut T| -> U) -> U {
197         let mut ptr = self.borrow_mut();
198         blk(ptr.get())
199     }
200
201     /// Sets the value, replacing what was there.
202     ///
203     /// # Failure
204     ///
205     /// Fails if the value is currently borrowed.
206     #[inline]
207     pub fn set(&self, value: T) {
208         let mut reference = self.borrow_mut();
209         *reference.get() = value
210     }
211 }
212
213 impl<T:Clone> RefCell<T> {
214     /// Returns a copy of the contained value.
215     ///
216     /// # Failure
217     ///
218     /// Fails if the value is currently mutably borrowed.
219     #[inline]
220     pub fn get(&self) -> T {
221         let reference = self.borrow();
222         (*reference.get()).clone()
223     }
224 }
225
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())
230     }
231 }
232
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())
237     }
238 }
239
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();
244         a.get() == b.get()
245     }
246 }
247
248 /// Wraps a borrowed reference to a value in a `RefCell` box.
249 pub struct Ref<'b, T> {
250     priv parent: &'b RefCell<T>
251 }
252
253 #[unsafe_destructor]
254 impl<'b, T> Drop for Ref<'b, T> {
255     fn drop(&mut self) {
256         assert!(self.parent.borrow != WRITING && self.parent.borrow != UNUSED);
257         unsafe { self.parent.as_mut().borrow -= 1; }
258     }
259 }
260
261 impl<'b, T> Ref<'b, T> {
262     /// Retrieve an immutable reference to the stored value.
263     #[inline]
264     pub fn get<'a>(&'a self) -> &'a T {
265         &self.parent.value
266     }
267 }
268
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>
272 }
273
274 #[unsafe_destructor]
275 impl<'b, T> Drop for RefMut<'b, T> {
276     fn drop(&mut self) {
277         assert!(self.parent.borrow == WRITING);
278         self.parent.borrow = UNUSED;
279     }
280 }
281
282 impl<'b, T> RefMut<'b, T> {
283     /// Retrieve a mutable reference to the stored value.
284     #[inline]
285     pub fn get<'a>(&'a mut self) -> &'a mut T {
286         &mut self.parent.value
287     }
288 }
289
290 #[cfg(test)]
291 mod test {
292     use super::*;
293
294     #[test]
295     fn smoketest_cell() {
296         let x = Cell::new(10);
297         assert_eq!(x.get(), 10);
298         x.set(20);
299         assert_eq!(x.get(), 20);
300
301         let y = Cell::new((30, 40));
302         assert_eq!(y.get(), (30, 40));
303     }
304
305     #[test]
306     fn double_imm_borrow() {
307         let x = RefCell::new(0);
308         let _b1 = x.borrow();
309         x.borrow();
310     }
311
312     #[test]
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());
317     }
318
319     #[test]
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());
324     }
325
326     #[test]
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());
331     }
332
333     #[test]
334     fn imm_release_borrow_mut() {
335         let x = RefCell::new(0);
336         {
337             let _b1 = x.borrow();
338         }
339         x.borrow_mut();
340     }
341
342     #[test]
343     fn mut_release_borrow_mut() {
344         let x = RefCell::new(0);
345         {
346             let _b1 = x.borrow_mut();
347         }
348         x.borrow();
349     }
350
351     #[test]
352     fn double_borrow_single_release_no_borrow_mut() {
353         let x = RefCell::new(0);
354         let _b1 = x.borrow();
355         {
356             let _b2 = x.borrow();
357         }
358         assert!(x.try_borrow_mut().is_none());
359     }
360
361     #[test]
362     fn with_ok() {
363         let x = RefCell::new(0);
364         assert_eq!(1, x.with(|x| *x+1));
365     }
366
367     #[test]
368     #[should_fail]
369     fn mut_borrow_with() {
370         let x = RefCell::new(0);
371         let _b1 = x.borrow_mut();
372         x.with(|x| *x+1);
373     }
374
375     #[test]
376     fn borrow_with() {
377         let x = RefCell::new(0);
378         let _b1 = x.borrow();
379         assert_eq!(1, x.with(|x| *x+1));
380     }
381
382     #[test]
383     fn with_mut_ok() {
384         let x = RefCell::new(0);
385         x.with_mut(|x| *x += 1);
386         let b = x.borrow();
387         assert_eq!(1, *b.get());
388     }
389
390     #[test]
391     #[should_fail]
392     fn borrow_with_mut() {
393         let x = RefCell::new(0);
394         let _b = x.borrow();
395         x.with_mut(|x| *x += 1);
396     }
397
398     #[test]
399     #[should_fail]
400     fn discard_doesnt_unborrow() {
401         let x = RefCell::new(0);
402         let _b = x.borrow();
403         let _ = _b;
404         let _b = x.borrow_mut();
405     }
406 }