(index<- ) ./libcore/cell.rs
git branch: * master 5200215 auto merge of #14035 : alexcrichton/rust/experimental, r=huonw
modified: Fri May 9 13:02:28 2014
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 that provide interior mutability.
12
13 use clone::Clone;
14 use cmp::Eq;
15 use kinds::{marker, Copy};
16 use ops::{Deref, DerefMut, Drop};
17 use option::{None, Option, Some};
18 use ty::Unsafe;
19
20 /// A mutable memory location that admits only `Copy` data.
21 pub struct Cell<T> {
22 value: Unsafe<T>,
23 noshare: marker::NoShare,
24 }
25
26 impl<T:Copy> Cell<T> {
27 /// Creates a new `Cell` containing the given value.
28 pub fn new(value: T) -> Cell<T> {
29 Cell {
30 value: Unsafe::new(value),
31 noshare: marker::NoShare,
32 }
33 }
34
35 /// Returns a copy of the contained value.
36 #[inline]
37 pub fn get(&self) -> T {
38 unsafe{ *self.value.get() }
39 }
40
41 /// Sets the contained value.
42 #[inline]
43 pub fn set(&self, value: T) {
44 unsafe {
45 *self.value.get() = value;
46 }
47 }
48 }
49
50 impl<T:Copy> Clone for Cell<T> {
51 fn clone(&self) -> Cell<T> {
52 Cell::new(self.get())
53 }
54 }
55
56 impl<T:Eq + Copy> Eq for Cell<T> {
57 fn eq(&self, other: &Cell<T>) -> bool {
58 self.get() == other.get()
59 }
60 }
61
62 /// A mutable memory location with dynamically checked borrow rules
63 pub struct RefCell<T> {
64 value: Unsafe<T>,
65 borrow: Cell<BorrowFlag>,
66 nocopy: marker::NoCopy,
67 noshare: marker::NoShare,
68 }
69
70 // Values [1, MAX-1] represent the number of `Ref` active
71 // (will not outgrow its range since `uint` is the size of the address space)
72 type BorrowFlag = uint;
73 static UNUSED: BorrowFlag = 0;
74 static WRITING: BorrowFlag = -1;
75
76 impl<T> RefCell<T> {
77 /// Create a new `RefCell` containing `value`
78 pub fn new(value: T) -> RefCell<T> {
79 RefCell {
80 value: Unsafe::new(value),
81 borrow: Cell::new(UNUSED),
82 nocopy: marker::NoCopy,
83 noshare: marker::NoShare,
84 }
85 }
86
87 /// Consumes the `RefCell`, returning the wrapped value.
88 pub fn unwrap(self) -> T {
89 debug_assert!(self.borrow.get() == UNUSED);
90 unsafe{self.value.unwrap()}
91 }
92
93 /// Attempts to immutably borrow the wrapped value.
94 ///
95 /// The borrow lasts until the returned `Ref` exits scope. Multiple
96 /// immutable borrows can be taken out at the same time.
97 ///
98 /// Returns `None` if the value is currently mutably borrowed.
99 pub fn try_borrow<'a>(&'a self) -> Option<Ref<'a, T>> {
100 match self.borrow.get() {
101 WRITING => None,
102 borrow => {
103 self.borrow.set(borrow + 1);
104 Some(Ref { parent: self })
105 }
106 }
107 }
108
109 /// Immutably borrows 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 /// # Failure
115 ///
116 /// Fails if the value is currently mutably borrowed.
117 pub fn borrow<'a>(&'a self) -> Ref<'a, T> {
118 match self.try_borrow() {
119 Some(ptr) => ptr,
120 None => fail!("RefCell<T> already mutably borrowed")
121 }
122 }
123
124 /// Mutably borrows the wrapped value.
125 ///
126 /// The borrow lasts until the returned `RefMut` exits scope. The value
127 /// cannot be borrowed while this borrow is active.
128 ///
129 /// Returns `None` if the value is currently borrowed.
130 pub fn try_borrow_mut<'a>(&'a self) -> Option<RefMut<'a, T>> {
131 match self.borrow.get() {
132 UNUSED => {
133 self.borrow.set(WRITING);
134 Some(RefMut { parent: self })
135 },
136 _ => None
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 /// # Failure
146 ///
147 /// Fails if the value is currently borrowed.
148 pub fn borrow_mut<'a>(&'a self) -> RefMut<'a, T> {
149 match self.try_borrow_mut() {
150 Some(ptr) => ptr,
151 None => fail!("RefCell<T> already borrowed")
152 }
153 }
154 }
155
156 impl<T: Clone> Clone for RefCell<T> {
157 fn clone(&self) -> RefCell<T> {
158 RefCell::new(self.borrow().clone())
159 }
160 }
161
162 impl<T: Eq> Eq for RefCell<T> {
163 fn eq(&self, other: &RefCell<T>) -> bool {
164 *self.borrow() == *other.borrow()
165 }
166 }
167
168 /// Wraps a borrowed reference to a value in a `RefCell` box.
169 pub struct Ref<'b, T> {
170 parent: &'b RefCell<T>
171 }
172
173 #[unsafe_destructor]
174 impl<'b, T> Drop for Ref<'b, T> {
175 fn drop(&mut self) {
176 let borrow = self.parent.borrow.get();
177 debug_assert!(borrow != WRITING && borrow != UNUSED);
178 self.parent.borrow.set(borrow - 1);
179 }
180 }
181
182 impl<'b, T> Deref<T> for Ref<'b, T> {
183 #[inline]
184 fn deref<'a>(&'a self) -> &'a T {
185 unsafe { &*self.parent.value.get() }
186 }
187 }
188
189 /// Wraps a mutable borrowed reference to a value in a `RefCell` box.
190 pub struct RefMut<'b, T> {
191 parent: &'b RefCell<T>
192 }
193
194 #[unsafe_destructor]
195 impl<'b, T> Drop for RefMut<'b, T> {
196 fn drop(&mut self) {
197 let borrow = self.parent.borrow.get();
198 debug_assert!(borrow == WRITING);
199 self.parent.borrow.set(UNUSED);
200 }
201 }
202
203 impl<'b, T> Deref<T> for RefMut<'b, T> {
204 #[inline]
205 fn deref<'a>(&'a self) -> &'a T {
206 unsafe { &*self.parent.value.get() }
207 }
208 }
209
210 impl<'b, T> DerefMut<T> for RefMut<'b, T> {
211 #[inline]
212 fn deref_mut<'a>(&'a mut self) -> &'a mut T {
213 unsafe { &mut *self.parent.value.get() }
214 }
215 }
216
217 #[cfg(test)]
218 mod test {
219 use super::*;
220
221 #[test]
222 fn smoketest_cell() {
223 let x = Cell::new(10);
224 assert!(x == Cell::new(10));
225 assert!(x.get() == 10);
226 x.set(20);
227 assert!(x == Cell::new(20));
228 assert!(x.get() == 20);
229
230 let y = Cell::new((30, 40));
231 assert!(y == Cell::new((30, 40)));
232 assert!(y.get() == (30, 40));
233 }
234
235 #[test]
236 fn cell_has_sensible_show() {
237 use str::StrSlice;
238
239 let x = ::realcore::cell::Cell::new("foo bar");
240 assert!(format!("{}", x).contains(x.get()));
241
242 x.set("baz qux");
243 assert!(format!("{}", x).contains(x.get()));
244 }
245
246 #[test]
247 fn double_imm_borrow() {
248 let x = RefCell::new(0);
249 let _b1 = x.borrow();
250 x.borrow();
251 }
252
253 #[test]
254 fn no_mut_then_imm_borrow() {
255 let x = RefCell::new(0);
256 let _b1 = x.borrow_mut();
257 assert!(x.try_borrow().is_none());
258 }
259
260 #[test]
261 fn no_imm_then_borrow_mut() {
262 let x = RefCell::new(0);
263 let _b1 = x.borrow();
264 assert!(x.try_borrow_mut().is_none());
265 }
266
267 #[test]
268 fn no_double_borrow_mut() {
269 let x = RefCell::new(0);
270 let _b1 = x.borrow_mut();
271 assert!(x.try_borrow_mut().is_none());
272 }
273
274 #[test]
275 fn imm_release_borrow_mut() {
276 let x = RefCell::new(0);
277 {
278 let _b1 = x.borrow();
279 }
280 x.borrow_mut();
281 }
282
283 #[test]
284 fn mut_release_borrow_mut() {
285 let x = RefCell::new(0);
286 {
287 let _b1 = x.borrow_mut();
288 }
289 x.borrow();
290 }
291
292 #[test]
293 fn double_borrow_single_release_no_borrow_mut() {
294 let x = RefCell::new(0);
295 let _b1 = x.borrow();
296 {
297 let _b2 = x.borrow();
298 }
299 assert!(x.try_borrow_mut().is_none());
300 }
301
302 #[test]
303 #[should_fail]
304 fn discard_doesnt_unborrow() {
305 let x = RefCell::new(0);
306 let _b = x.borrow();
307 let _ = _b;
308 let _b = x.borrow_mut();
309 }
310 }
libcore/cell.rs:20:60-20:60 -struct- definition:
/// A mutable memory location that admits only `Copy` data.
pub struct Cell<T> {
value: Unsafe<T>,
references:- 828: pub fn new(value: T) -> Cell<T> {
29: Cell {
30: value: Unsafe::new(value),
--
56: impl<T:Eq + Copy> Eq for Cell<T> {
57: fn eq(&self, other: &Cell<T>) -> bool {
58: self.get() == other.get()
--
64: value: Unsafe<T>,
65: borrow: Cell<BorrowFlag>,
66: nocopy: marker::NoCopy,
libcore/cell.rs:71:78-71:78 -NK_AS_STR_TODO- definition:
// (will not outgrow its range since `uint` is the size of the address space)
type BorrowFlag = uint;
static UNUSED: BorrowFlag = 0;
references:- 373: static UNUSED: BorrowFlag = 0;
74: static WRITING: BorrowFlag = -1;
libcore/cell.rs:62:68-62:68 -struct- definition:
/// A mutable memory location with dynamically checked borrow rules
pub struct RefCell<T> {
value: Unsafe<T>,
references:- 978: pub fn new(value: T) -> RefCell<T> {
79: RefCell {
80: value: Unsafe::new(value),
--
156: impl<T: Clone> Clone for RefCell<T> {
157: fn clone(&self) -> RefCell<T> {
158: RefCell::new(self.borrow().clone())
--
190: pub struct RefMut<'b, T> {
191: parent: &'b RefCell<T>
192: }
libcore/cell.rs:189:70-189:70 -struct- definition:
/// Wraps a mutable borrowed reference to a value in a `RefCell` box.
pub struct RefMut<'b, T> {
parent: &'b RefCell<T>
references:- 6133: self.borrow.set(WRITING);
134: Some(RefMut { parent: self })
135: },
--
210: impl<'b, T> DerefMut<T> for RefMut<'b, T> {
211: #[inline]
libcore/cell.rs:168:62-168:62 -struct- definition:
/// Wraps a borrowed reference to a value in a `RefCell` box.
pub struct Ref<'b, T> {
parent: &'b RefCell<T>
references:- 5103: self.borrow.set(borrow + 1);
104: Some(Ref { parent: self })
105: }
--
174: impl<'b, T> Drop for Ref<'b, T> {
175: fn drop(&mut self) {
--
182: impl<'b, T> Deref<T> for Ref<'b, T> {
183: #[inline]