8
8
// option. This file may not be copied, modified, or distributed
9
9
// except according to those terms.
10
10
11
- //! Runtime move semantics
11
+ //! Types dealing with dynamic mutability
12
12
13
13
#[missing_doc];
14
14
15
- use cast::transmute_mut;
16
15
use prelude::*;
16
+ use cast;
17
+ use util::NonCopyable;
18
+
17
19
18
20
/*
19
21
A dynamic, mutable location.
@@ -36,7 +38,7 @@ impl<T> Cell<T> {
36
38
37
39
/// Yields the value, failing if the cell is empty.
38
40
pub fn take(&self) -> T {
39
- let this = unsafe { transmute_mut(self) };
41
+ let this = unsafe { cast:: transmute_mut(self) };
40
42
if this.is_empty() {
41
43
fail!("attempt to take an empty cell");
42
44
}
@@ -46,7 +48,7 @@ impl<T> Cell<T> {
46
48
47
49
/// Yields the value if the cell is full, or `None` if it is empty.
48
50
pub fn take_opt(&self) -> Option<T> {
49
- let this = unsafe { transmute_mut(self) };
51
+ let this = unsafe { cast:: transmute_mut(self) };
50
52
this.value.take()
51
53
}
52
54
@@ -72,3 +74,295 @@ fn test_take_empty() {
72
74
value_cell.take();
73
75
value_cell.take();
74
76
}
77
+
78
+
79
+ /// A mutable memory location with dynamically checked borrow rules
80
+ #[no_freeze]
81
+ pub struct RefCell<T> {
82
+ priv value: T,
83
+ priv borrow: BorrowFlag,
84
+ priv nc: NonCopyable
85
+ }
86
+
87
+ // Values [1, MAX-1] represent the number of `Ref` active
88
+ // (will not outgrow its range since `uint` is the size of the address space)
89
+ type BorrowFlag = uint;
90
+ static UNUSED: BorrowFlag = 0;
91
+ static WRITING: BorrowFlag = -1;
92
+
93
+ impl<T> RefCell<T> {
94
+ /// Create a new `RefCell` containing `value`
95
+ pub fn new(value: T) -> RefCell<T> {
96
+ RefCell {
97
+ value: value,
98
+ borrow: UNUSED,
99
+ nc: NonCopyable
100
+ }
101
+ }
102
+
103
+ /// Consumes the `RefCell`, returning the wrapped value.
104
+ pub fn unwrap(self) -> T {
105
+ assert!(self.borrow == UNUSED);
106
+ self.value
107
+ }
108
+
109
+ unsafe fn as_mut<'a>(&'a self) -> &'a mut RefCell<T> {
110
+ cast::transmute_mut(self)
111
+ }
112
+
113
+ /// Attempts to immutably borrow the wrapped value.
114
+ ///
115
+ /// The borrow lasts until the returned `Ref` exits scope. Multiple
116
+ /// immutable borrows can be taken out at the same time.
117
+ ///
118
+ /// Returns `None` if the value is currently mutably borrowed.
119
+ pub fn try_borrow<'a>(&'a self) -> Option<Ref<'a, T>> {
120
+ match self.borrow {
121
+ WRITING => None,
122
+ _ => {
123
+ unsafe { self.as_mut().borrow += 1; }
124
+ Some(Ref { parent: self })
125
+ }
126
+ }
127
+ }
128
+
129
+ /// Immutably borrows the wrapped value.
130
+ ///
131
+ /// The borrow lasts until the returned `Ref` exits scope. Multiple
132
+ /// immutable borrows can be taken out at the same time.
133
+ ///
134
+ /// # Failure
135
+ ///
136
+ /// Fails if the value is currently mutably borrowed.
137
+ pub fn borrow<'a>(&'a self) -> Ref<'a, T> {
138
+ match self.try_borrow() {
139
+ Some(ptr) => ptr,
140
+ None => fail!("RefCell<T> already mutably borrowed")
141
+ }
142
+ }
143
+
144
+ /// Mutably borrows the wrapped value.
145
+ ///
146
+ /// The borrow lasts untile the returned `RefMut` exits scope. The value
147
+ /// cannot be borrowed while this borrow is active.
148
+ ///
149
+ /// Returns `None` if the value is currently borrowed.
150
+ pub fn try_borrow_mut<'a>(&'a self) -> Option<RefMut<'a, T>> {
151
+ match self.borrow {
152
+ UNUSED => unsafe {
153
+ let mut_self = self.as_mut();
154
+ mut_self.borrow = WRITING;
155
+ Some(RefMut { parent: mut_self })
156
+ },
157
+ _ => None
158
+ }
159
+ }
160
+
161
+ /// Mutably borrows the wrapped value.
162
+ ///
163
+ /// The borrow lasts untile the returned `RefMut` exits scope. The value
164
+ /// cannot be borrowed while this borrow is active.
165
+ ///
166
+ /// # Failure
167
+ ///
168
+ /// Fails if the value is currently borrowed.
169
+ pub fn borrow_mut<'a>(&'a self) -> RefMut<'a, T> {
170
+ match self.try_borrow_mut() {
171
+ Some(ptr) => ptr,
172
+ None => fail!("RefCell<T> already borrowed")
173
+ }
174
+ }
175
+
176
+ /// Immutably borrows the wrapped value and applies `blk` to it.
177
+ ///
178
+ /// # Failure
179
+ ///
180
+ /// Fails if the value is currently mutably borrowed.
181
+ #[inline]
182
+ pub fn with<U>(&self, blk: |&T| -> U) -> U {
183
+ let ptr = self.borrow();
184
+ blk(ptr.get())
185
+ }
186
+
187
+ /// Mutably borrows the wrapped value and applies `blk` to it.
188
+ ///
189
+ /// # Failure
190
+ ///
191
+ /// Fails if the value is currently borrowed.
192
+ #[inline]
193
+ pub fn with_mut<U>(&self, blk: |&mut T| -> U) -> U {
194
+ let mut ptr = self.borrow_mut();
195
+ blk(ptr.get())
196
+ }
197
+ }
198
+
199
+ impl<T: Clone> Clone for RefCell<T> {
200
+ fn clone(&self) -> RefCell<T> {
201
+ let x = self.borrow();
202
+ RefCell::new(x.get().clone())
203
+ }
204
+ }
205
+
206
+ impl<T: DeepClone> DeepClone for RefCell<T> {
207
+ fn deep_clone(&self) -> RefCell<T> {
208
+ let x = self.borrow();
209
+ RefCell::new(x.get().deep_clone())
210
+ }
211
+ }
212
+
213
+ impl<T: Eq> Eq for RefCell<T> {
214
+ fn eq(&self, other: &RefCell<T>) -> bool {
215
+ let a = self.borrow();
216
+ let b = other.borrow();
217
+ a.get() == b.get()
218
+ }
219
+ }
220
+
221
+ /// Wraps a borrowed reference to a value in a `RefCell` box.
222
+ pub struct Ref<'box, T> {
223
+ priv parent: &'box RefCell<T>
224
+ }
225
+
226
+ #[unsafe_destructor]
227
+ impl<'box, T> Drop for Ref<'box, T> {
228
+ fn drop(&mut self) {
229
+ assert!(self.parent.borrow != WRITING && self.parent.borrow != UNUSED);
230
+ unsafe { self.parent.as_mut().borrow -= 1; }
231
+ }
232
+ }
233
+
234
+ impl<'box, T> Ref<'box, T> {
235
+ /// Retrieve an immutable reference to the stored value.
236
+ #[inline]
237
+ pub fn get<'a>(&'a self) -> &'a T {
238
+ &self.parent.value
239
+ }
240
+ }
241
+
242
+ /// Wraps a mutable borrowed reference to a value in a `RefCell` box.
243
+ pub struct RefMut<'box, T> {
244
+ priv parent: &'box mut RefCell<T>
245
+ }
246
+
247
+ #[unsafe_destructor]
248
+ impl<'box, T> Drop for RefMut<'box, T> {
249
+ fn drop(&mut self) {
250
+ assert!(self.parent.borrow == WRITING);
251
+ self.parent.borrow = UNUSED;
252
+ }
253
+ }
254
+
255
+ impl<'box, T> RefMut<'box, T> {
256
+ /// Retrieve a mutable reference to the stored value.
257
+ #[inline]
258
+ pub fn get<'a>(&'a mut self) -> &'a mut T {
259
+ &mut self.parent.value
260
+ }
261
+ }
262
+
263
+ #[cfg(test)]
264
+ mod test {
265
+ use super::*;
266
+
267
+ #[test]
268
+ fn double_imm_borrow() {
269
+ let x = RefCell::new(0);
270
+ let _b1 = x.borrow();
271
+ x.borrow();
272
+ }
273
+
274
+ #[test]
275
+ fn no_mut_then_imm_borrow() {
276
+ let x = RefCell::new(0);
277
+ let _b1 = x.borrow_mut();
278
+ assert!(x.try_borrow().is_none());
279
+ }
280
+
281
+ #[test]
282
+ fn no_imm_then_borrow_mut() {
283
+ let x = RefCell::new(0);
284
+ let _b1 = x.borrow();
285
+ assert!(x.try_borrow_mut().is_none());
286
+ }
287
+
288
+ #[test]
289
+ fn no_double_borrow_mut() {
290
+ let x = RefCell::new(0);
291
+ let _b1 = x.borrow_mut();
292
+ assert!(x.try_borrow_mut().is_none());
293
+ }
294
+
295
+ #[test]
296
+ fn imm_release_borrow_mut() {
297
+ let x = RefCell::new(0);
298
+ {
299
+ let _b1 = x.borrow();
300
+ }
301
+ x.borrow_mut();
302
+ }
303
+
304
+ #[test]
305
+ fn mut_release_borrow_mut() {
306
+ let x = RefCell::new(0);
307
+ {
308
+ let _b1 = x.borrow_mut();
309
+ }
310
+ x.borrow();
311
+ }
312
+
313
+ #[test]
314
+ fn double_borrow_single_release_no_borrow_mut() {
315
+ let x = RefCell::new(0);
316
+ let _b1 = x.borrow();
317
+ {
318
+ let _b2 = x.borrow();
319
+ }
320
+ assert!(x.try_borrow_mut().is_none());
321
+ }
322
+
323
+ #[test]
324
+ fn with_ok() {
325
+ let x = RefCell::new(0);
326
+ assert_eq!(1, x.with(|x| *x+1));
327
+ }
328
+
329
+ #[test]
330
+ #[should_fail]
331
+ fn mut_borrow_with() {
332
+ let x = RefCell::new(0);
333
+ let _b1 = x.borrow_mut();
334
+ x.with(|x| *x+1);
335
+ }
336
+
337
+ #[test]
338
+ fn borrow_with() {
339
+ let x = RefCell::new(0);
340
+ let _b1 = x.borrow();
341
+ assert_eq!(1, x.with(|x| *x+1));
342
+ }
343
+
344
+ #[test]
345
+ fn with_mut_ok() {
346
+ let x = RefCell::new(0);
347
+ x.with_mut(|x| *x += 1);
348
+ let b = x.borrow();
349
+ assert_eq!(1, *b.get());
350
+ }
351
+
352
+ #[test]
353
+ #[should_fail]
354
+ fn borrow_with_mut() {
355
+ let x = RefCell::new(0);
356
+ let _b = x.borrow();
357
+ x.with_mut(|x| *x += 1);
358
+ }
359
+
360
+ #[test]
361
+ #[should_fail]
362
+ fn discard_doesnt_unborrow() {
363
+ let x = RefCell::new(0);
364
+ let _b = x.borrow();
365
+ let _ = _b;
366
+ let _b = x.borrow_mut();
367
+ }
368
+ }
0 commit comments