]> git.lizzy.rs Git - rust.git/blob - src/libstd/cell.rs
rand: Use fill() instead of read()
[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 cast;
14 use clone::Clone;
15 use cmp::Eq;
16 use fmt;
17 use kinds::{marker, Pod};
18 use ops::{Deref, DerefMut, Drop};
19 use option::{None, Option, Some};
20 use ty::Unsafe;
21
22 /// A mutable memory location that admits only `Pod` data.
23 pub struct Cell<T> {
24     priv value: Unsafe<T>,
25     priv marker1: marker::NoFreeze,
26     priv marker2: marker::NoShare,
27 }
28
29 impl<T:Pod> Cell<T> {
30     /// Creates a new `Cell` containing the given value.
31     pub fn new(value: T) -> Cell<T> {
32         Cell {
33             value: Unsafe::new(value),
34             marker1: marker::NoFreeze,
35             marker2: marker::NoShare,
36         }
37     }
38
39     /// Returns a copy of the contained value.
40     #[inline]
41     pub fn get(&self) -> T {
42         unsafe{ *self.value.get() }
43     }
44
45     /// Sets the contained value.
46     #[inline]
47     pub fn set(&self, value: T) {
48         unsafe {
49             *self.value.get() = value;
50         }
51     }
52 }
53
54 impl<T:Pod> Clone for Cell<T> {
55     fn clone(&self) -> Cell<T> {
56         Cell::new(self.get())
57     }
58 }
59
60 impl<T:Eq + Pod> Eq for Cell<T> {
61     fn eq(&self, other: &Cell<T>) -> bool {
62         self.get() == other.get()
63     }
64 }
65
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()})
69     }
70 }
71
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,
79 }
80
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;
86
87 impl<T> RefCell<T> {
88     /// Create a new `RefCell` containing `value`
89     pub fn new(value: T) -> RefCell<T> {
90         RefCell {
91             marker1: marker::NoFreeze,
92             marker2: marker::NoPod,
93             marker3: marker::NoShare,
94             value: Unsafe::new(value),
95             borrow: UNUSED,
96         }
97     }
98
99     /// Consumes the `RefCell`, returning the wrapped value.
100     pub fn unwrap(self) -> T {
101         assert!(self.borrow == UNUSED);
102         unsafe{self.value.unwrap()}
103     }
104
105     unsafe fn as_mut<'a>(&'a self) -> &'a mut RefCell<T> {
106         cast::transmute_mut(self)
107     }
108
109     /// Attempts to immutably borrow the wrapped value.
110     ///
111     /// The borrow lasts until the returned `Ref` exits scope. Multiple
112     /// immutable borrows can be taken out at the same time.
113     ///
114     /// Returns `None` if the value is currently mutably borrowed.
115     pub fn try_borrow<'a>(&'a self) -> Option<Ref<'a, T>> {
116         match self.borrow {
117             WRITING => None,
118             _ => {
119                 unsafe { self.as_mut().borrow += 1; }
120                 Some(Ref { parent: self })
121             }
122         }
123     }
124
125     /// Immutably borrows the wrapped value.
126     ///
127     /// The borrow lasts until the returned `Ref` exits scope. Multiple
128     /// immutable borrows can be taken out at the same time.
129     ///
130     /// # Failure
131     ///
132     /// Fails if the value is currently mutably borrowed.
133     pub fn borrow<'a>(&'a self) -> Ref<'a, T> {
134         match self.try_borrow() {
135             Some(ptr) => ptr,
136             None => fail!("RefCell<T> already mutably borrowed")
137         }
138     }
139
140     /// Mutably borrows the wrapped value.
141     ///
142     /// The borrow lasts until the returned `RefMut` exits scope. The value
143     /// cannot be borrowed while this borrow is active.
144     ///
145     /// Returns `None` if the value is currently borrowed.
146     pub fn try_borrow_mut<'a>(&'a self) -> Option<RefMut<'a, T>> {
147         match self.borrow {
148             UNUSED => unsafe {
149                 let mut_self = self.as_mut();
150                 mut_self.borrow = WRITING;
151                 Some(RefMut { parent: mut_self })
152             },
153             _ => None
154         }
155     }
156
157     /// Mutably borrows the wrapped value.
158     ///
159     /// The borrow lasts until the returned `RefMut` exits scope. The value
160     /// cannot be borrowed while this borrow is active.
161     ///
162     /// # Failure
163     ///
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() {
167             Some(ptr) => ptr,
168             None => fail!("RefCell<T> already borrowed")
169         }
170     }
171
172     /// Sets the value, replacing what was there.
173     ///
174     /// # Failure
175     ///
176     /// Fails if the value is currently borrowed.
177     #[inline]
178     pub fn set(&self, value: T) {
179         let mut reference = self.borrow_mut();
180         *reference.get() = value;
181     }
182 }
183
184 impl<T:Clone> RefCell<T> {
185     /// Returns a copy of the contained value.
186     ///
187     /// # Failure
188     ///
189     /// Fails if the value is currently mutably borrowed.
190     #[inline]
191     pub fn get(&self) -> T {
192         let reference = self.borrow();
193         (*reference.get()).clone()
194     }
195 }
196
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())
201     }
202 }
203
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();
208         a.get() == b.get()
209     }
210 }
211
212 /// Wraps a borrowed reference to a value in a `RefCell` box.
213 pub struct Ref<'b, T> {
214     priv parent: &'b RefCell<T>
215 }
216
217 #[unsafe_destructor]
218 impl<'b, T> Drop for Ref<'b, T> {
219     fn drop(&mut self) {
220         assert!(self.parent.borrow != WRITING && self.parent.borrow != UNUSED);
221         unsafe { self.parent.as_mut().borrow -= 1; }
222     }
223 }
224
225 impl<'b, T> Ref<'b, T> {
226     /// Retrieve an immutable reference to the stored value.
227     #[inline]
228     pub fn get<'a>(&'a self) -> &'a T {
229         unsafe{ &*self.parent.value.get() }
230     }
231 }
232
233 impl<'b, T> Deref<T> for Ref<'b, T> {
234     #[inline]
235     fn deref<'a>(&'a self) -> &'a T {
236         unsafe{ &*self.parent.value.get() }
237     }
238 }
239
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>
243 }
244
245 #[unsafe_destructor]
246 impl<'b, T> Drop for RefMut<'b, T> {
247     fn drop(&mut self) {
248         assert!(self.parent.borrow == WRITING);
249         self.parent.borrow = UNUSED;
250     }
251 }
252
253 impl<'b, T> RefMut<'b, T> {
254     /// Retrieve a mutable reference to the stored value.
255     #[inline]
256     pub fn get<'a>(&'a mut self) -> &'a mut T {
257         unsafe{ &mut *self.parent.value.get() }
258     }
259 }
260
261 impl<'b, T> Deref<T> for RefMut<'b, T> {
262     #[inline]
263     fn deref<'a>(&'a self) -> &'a T {
264         unsafe{ &*self.parent.value.get() }
265     }
266 }
267
268 impl<'b, T> DerefMut<T> for RefMut<'b, T> {
269     #[inline]
270     fn deref_mut<'a>(&'a mut self) -> &'a mut T {
271         unsafe{ &mut *self.parent.value.get() }
272     }
273 }
274
275 #[cfg(test)]
276 mod test {
277     use super::*;
278
279     #[test]
280     fn smoketest_cell() {
281         let x = Cell::new(10);
282         assert_eq!(x, Cell::new(10));
283         assert_eq!(x.get(), 10);
284         x.set(20);
285         assert_eq!(x, Cell::new(20));
286         assert_eq!(x.get(), 20);
287
288         let y = Cell::new((30, 40));
289         assert_eq!(y, Cell::new((30, 40)));
290         assert_eq!(y.get(), (30, 40));
291     }
292
293     #[test]
294     fn double_imm_borrow() {
295         let x = RefCell::new(0);
296         let _b1 = x.borrow();
297         x.borrow();
298     }
299
300     #[test]
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());
305     }
306
307     #[test]
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());
312     }
313
314     #[test]
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());
319     }
320
321     #[test]
322     fn imm_release_borrow_mut() {
323         let x = RefCell::new(0);
324         {
325             let _b1 = x.borrow();
326         }
327         x.borrow_mut();
328     }
329
330     #[test]
331     fn mut_release_borrow_mut() {
332         let x = RefCell::new(0);
333         {
334             let _b1 = x.borrow_mut();
335         }
336         x.borrow();
337     }
338
339     #[test]
340     fn double_borrow_single_release_no_borrow_mut() {
341         let x = RefCell::new(0);
342         let _b1 = x.borrow();
343         {
344             let _b2 = x.borrow();
345         }
346         assert!(x.try_borrow_mut().is_none());
347     }
348
349     #[test]
350     #[should_fail]
351     fn discard_doesnt_unborrow() {
352         let x = RefCell::new(0);
353         let _b = x.borrow();
354         let _ = _b;
355         let _b = x.borrow_mut();
356     }
357 }