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