]>
Commit | Line | Data |
---|---|---|
85aaf69f | 1 | // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT |
1a4d82fc JJ |
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 | //! Shareable mutable containers. | |
12 | //! | |
85aaf69f SL |
13 | //! Values of the `Cell<T>` and `RefCell<T>` types may be mutated through shared references (i.e. |
14 | //! the common `&T` type), whereas most Rust types can only be mutated through unique (`&mut T`) | |
15 | //! references. We say that `Cell<T>` and `RefCell<T>` provide 'interior mutability', in contrast | |
16 | //! with typical Rust types that exhibit 'inherited mutability'. | |
1a4d82fc | 17 | //! |
85aaf69f SL |
18 | //! Cell types come in two flavors: `Cell<T>` and `RefCell<T>`. `Cell<T>` provides `get` and `set` |
19 | //! methods that change the interior value with a single method call. `Cell<T>` though is only | |
20 | //! compatible with types that implement `Copy`. For other types, one must use the `RefCell<T>` | |
21 | //! type, acquiring a write lock before mutating. | |
1a4d82fc | 22 | //! |
85aaf69f SL |
23 | //! `RefCell<T>` uses Rust's lifetimes to implement 'dynamic borrowing', a process whereby one can |
24 | //! claim temporary, exclusive, mutable access to the inner value. Borrows for `RefCell<T>`s are | |
25 | //! tracked 'at runtime', unlike Rust's native reference types which are entirely tracked | |
26 | //! statically, at compile time. Because `RefCell<T>` borrows are dynamic it is possible to attempt | |
bd371182 AL |
27 | //! to borrow a value that is already mutably borrowed; when this happens it results in thread |
28 | //! panic. | |
1a4d82fc JJ |
29 | //! |
30 | //! # When to choose interior mutability | |
31 | //! | |
85aaf69f SL |
32 | //! The more common inherited mutability, where one must have unique access to mutate a value, is |
33 | //! one of the key language elements that enables Rust to reason strongly about pointer aliasing, | |
34 | //! statically preventing crash bugs. Because of that, inherited mutability is preferred, and | |
35 | //! interior mutability is something of a last resort. Since cell types enable mutation where it | |
36 | //! would otherwise be disallowed though, there are occasions when interior mutability might be | |
37 | //! appropriate, or even *must* be used, e.g. | |
1a4d82fc | 38 | //! |
c1a9b12d | 39 | //! * Introducing mutability 'inside' of something immutable |
1a4d82fc | 40 | //! * Implementation details of logically-immutable methods. |
62682a34 | 41 | //! * Mutating implementations of `Clone`. |
1a4d82fc | 42 | //! |
c1a9b12d | 43 | //! ## Introducing mutability 'inside' of something immutable |
1a4d82fc | 44 | //! |
c1a9b12d | 45 | //! Many shared smart pointer types, including `Rc<T>` and `Arc<T>`, provide containers that can be |
85aaf69f | 46 | //! cloned and shared between multiple parties. Because the contained values may be |
c1a9b12d SL |
47 | //! multiply-aliased, they can only be borrowed with `&`, not `&mut`. Without cells it would be |
48 | //! impossible to mutate data inside of these smart pointers at all. | |
1a4d82fc | 49 | //! |
85aaf69f SL |
50 | //! It's very common then to put a `RefCell<T>` inside shared pointer types to reintroduce |
51 | //! mutability: | |
1a4d82fc JJ |
52 | //! |
53 | //! ``` | |
54 | //! use std::collections::HashMap; | |
55 | //! use std::cell::RefCell; | |
56 | //! use std::rc::Rc; | |
57 | //! | |
58 | //! fn main() { | |
59 | //! let shared_map: Rc<RefCell<_>> = Rc::new(RefCell::new(HashMap::new())); | |
85aaf69f SL |
60 | //! shared_map.borrow_mut().insert("africa", 92388); |
61 | //! shared_map.borrow_mut().insert("kyoto", 11837); | |
62 | //! shared_map.borrow_mut().insert("piccadilly", 11826); | |
63 | //! shared_map.borrow_mut().insert("marbles", 38); | |
1a4d82fc JJ |
64 | //! } |
65 | //! ``` | |
66 | //! | |
85aaf69f | 67 | //! Note that this example uses `Rc<T>` and not `Arc<T>`. `RefCell<T>`s are for single-threaded |
c1a9b12d SL |
68 | //! scenarios. Consider using `RwLock<T>` or `Mutex<T>` if you need shared mutability in a |
69 | //! multi-threaded situation. | |
85aaf69f | 70 | //! |
1a4d82fc JJ |
71 | //! ## Implementation details of logically-immutable methods |
72 | //! | |
85aaf69f SL |
73 | //! Occasionally it may be desirable not to expose in an API that there is mutation happening |
74 | //! "under the hood". This may be because logically the operation is immutable, but e.g. caching | |
75 | //! forces the implementation to perform mutation; or because you must employ mutation to implement | |
76 | //! a trait method that was originally defined to take `&self`. | |
1a4d82fc JJ |
77 | //! |
78 | //! ``` | |
79 | //! use std::cell::RefCell; | |
80 | //! | |
81 | //! struct Graph { | |
85aaf69f SL |
82 | //! edges: Vec<(i32, i32)>, |
83 | //! span_tree_cache: RefCell<Option<Vec<(i32, i32)>>> | |
1a4d82fc JJ |
84 | //! } |
85 | //! | |
86 | //! impl Graph { | |
85aaf69f | 87 | //! fn minimum_spanning_tree(&self) -> Vec<(i32, i32)> { |
1a4d82fc JJ |
88 | //! // Create a new scope to contain the lifetime of the |
89 | //! // dynamic borrow | |
90 | //! { | |
91 | //! // Take a reference to the inside of cache cell | |
92 | //! let mut cache = self.span_tree_cache.borrow_mut(); | |
93 | //! if cache.is_some() { | |
94 | //! return cache.as_ref().unwrap().clone(); | |
95 | //! } | |
96 | //! | |
97 | //! let span_tree = self.calc_span_tree(); | |
98 | //! *cache = Some(span_tree); | |
99 | //! } | |
100 | //! | |
101 | //! // Recursive call to return the just-cached value. | |
102 | //! // Note that if we had not let the previous borrow | |
103 | //! // of the cache fall out of scope then the subsequent | |
bd371182 | 104 | //! // recursive borrow would cause a dynamic thread panic. |
1a4d82fc JJ |
105 | //! // This is the major hazard of using `RefCell`. |
106 | //! self.minimum_spanning_tree() | |
107 | //! } | |
85aaf69f | 108 | //! # fn calc_span_tree(&self) -> Vec<(i32, i32)> { vec![] } |
1a4d82fc | 109 | //! } |
1a4d82fc JJ |
110 | //! ``` |
111 | //! | |
62682a34 | 112 | //! ## Mutating implementations of `Clone` |
1a4d82fc | 113 | //! |
85aaf69f SL |
114 | //! This is simply a special - but common - case of the previous: hiding mutability for operations |
115 | //! that appear to be immutable. The `clone` method is expected to not change the source value, and | |
116 | //! is declared to take `&self`, not `&mut self`. Therefore any mutation that happens in the | |
117 | //! `clone` method must use cell types. For example, `Rc<T>` maintains its reference counts within a | |
118 | //! `Cell<T>`. | |
1a4d82fc JJ |
119 | //! |
120 | //! ``` | |
121 | //! use std::cell::Cell; | |
122 | //! | |
123 | //! struct Rc<T> { | |
124 | //! ptr: *mut RcBox<T> | |
125 | //! } | |
126 | //! | |
127 | //! struct RcBox<T> { | |
128 | //! value: T, | |
85aaf69f | 129 | //! refcount: Cell<usize> |
1a4d82fc JJ |
130 | //! } |
131 | //! | |
132 | //! impl<T> Clone for Rc<T> { | |
133 | //! fn clone(&self) -> Rc<T> { | |
134 | //! unsafe { | |
135 | //! (*self.ptr).refcount.set((*self.ptr).refcount.get() + 1); | |
136 | //! Rc { ptr: self.ptr } | |
137 | //! } | |
138 | //! } | |
139 | //! } | |
140 | //! ``` | |
141 | //! | |
1a4d82fc | 142 | |
85aaf69f | 143 | #![stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
144 | |
145 | use clone::Clone; | |
62682a34 | 146 | use cmp::{PartialEq, Eq}; |
1a4d82fc | 147 | use default::Default; |
d9579d0f | 148 | use marker::{Copy, Send, Sync, Sized}; |
62682a34 | 149 | use ops::{Deref, DerefMut, Drop, FnOnce}; |
1a4d82fc JJ |
150 | use option::Option; |
151 | use option::Option::{None, Some}; | |
152 | ||
153 | /// A mutable memory location that admits only `Copy` data. | |
85aaf69f SL |
154 | /// |
155 | /// See the [module-level documentation](index.html) for more. | |
156 | #[stable(feature = "rust1", since = "1.0.0")] | |
1a4d82fc JJ |
157 | pub struct Cell<T> { |
158 | value: UnsafeCell<T>, | |
159 | } | |
160 | ||
161 | impl<T:Copy> Cell<T> { | |
162 | /// Creates a new `Cell` containing the given value. | |
85aaf69f SL |
163 | /// |
164 | /// # Examples | |
165 | /// | |
166 | /// ``` | |
167 | /// use std::cell::Cell; | |
168 | /// | |
169 | /// let c = Cell::new(5); | |
170 | /// ``` | |
171 | #[stable(feature = "rust1", since = "1.0.0")] | |
c34b1796 | 172 | #[inline] |
62682a34 | 173 | pub const fn new(value: T) -> Cell<T> { |
1a4d82fc JJ |
174 | Cell { |
175 | value: UnsafeCell::new(value), | |
176 | } | |
177 | } | |
178 | ||
179 | /// Returns a copy of the contained value. | |
85aaf69f SL |
180 | /// |
181 | /// # Examples | |
182 | /// | |
183 | /// ``` | |
184 | /// use std::cell::Cell; | |
185 | /// | |
186 | /// let c = Cell::new(5); | |
187 | /// | |
188 | /// let five = c.get(); | |
189 | /// ``` | |
1a4d82fc | 190 | #[inline] |
85aaf69f | 191 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
192 | pub fn get(&self) -> T { |
193 | unsafe{ *self.value.get() } | |
194 | } | |
195 | ||
196 | /// Sets the contained value. | |
85aaf69f SL |
197 | /// |
198 | /// # Examples | |
199 | /// | |
200 | /// ``` | |
201 | /// use std::cell::Cell; | |
202 | /// | |
203 | /// let c = Cell::new(5); | |
204 | /// | |
205 | /// c.set(10); | |
206 | /// ``` | |
1a4d82fc | 207 | #[inline] |
85aaf69f | 208 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
209 | pub fn set(&self, value: T) { |
210 | unsafe { | |
211 | *self.value.get() = value; | |
212 | } | |
213 | } | |
214 | ||
62682a34 | 215 | /// Returns a reference to the underlying `UnsafeCell`. |
1a4d82fc | 216 | /// |
85aaf69f | 217 | /// # Unsafety |
1a4d82fc JJ |
218 | /// |
219 | /// This function is `unsafe` because `UnsafeCell`'s field is public. | |
85aaf69f SL |
220 | /// |
221 | /// # Examples | |
222 | /// | |
223 | /// ``` | |
c1a9b12d SL |
224 | /// #![feature(as_unsafe_cell)] |
225 | /// | |
85aaf69f SL |
226 | /// use std::cell::Cell; |
227 | /// | |
228 | /// let c = Cell::new(5); | |
229 | /// | |
230 | /// let uc = unsafe { c.as_unsafe_cell() }; | |
231 | /// ``` | |
1a4d82fc | 232 | #[inline] |
e9174d1e SL |
233 | #[unstable(feature = "as_unsafe_cell", issue = "27708")] |
234 | pub unsafe fn as_unsafe_cell(&self) -> &UnsafeCell<T> { | |
1a4d82fc JJ |
235 | &self.value |
236 | } | |
237 | } | |
238 | ||
85aaf69f | 239 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc JJ |
240 | unsafe impl<T> Send for Cell<T> where T: Send {} |
241 | ||
85aaf69f | 242 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc | 243 | impl<T:Copy> Clone for Cell<T> { |
c34b1796 | 244 | #[inline] |
1a4d82fc JJ |
245 | fn clone(&self) -> Cell<T> { |
246 | Cell::new(self.get()) | |
247 | } | |
248 | } | |
249 | ||
85aaf69f | 250 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc | 251 | impl<T:Default + Copy> Default for Cell<T> { |
85aaf69f | 252 | #[stable(feature = "rust1", since = "1.0.0")] |
c34b1796 | 253 | #[inline] |
1a4d82fc JJ |
254 | fn default() -> Cell<T> { |
255 | Cell::new(Default::default()) | |
256 | } | |
257 | } | |
258 | ||
85aaf69f | 259 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc | 260 | impl<T:PartialEq + Copy> PartialEq for Cell<T> { |
c34b1796 | 261 | #[inline] |
1a4d82fc JJ |
262 | fn eq(&self, other: &Cell<T>) -> bool { |
263 | self.get() == other.get() | |
264 | } | |
265 | } | |
266 | ||
62682a34 SL |
267 | #[stable(feature = "cell_eq", since = "1.2.0")] |
268 | impl<T:Eq + Copy> Eq for Cell<T> {} | |
269 | ||
1a4d82fc | 270 | /// A mutable memory location with dynamically checked borrow rules |
85aaf69f SL |
271 | /// |
272 | /// See the [module-level documentation](index.html) for more. | |
273 | #[stable(feature = "rust1", since = "1.0.0")] | |
d9579d0f | 274 | pub struct RefCell<T: ?Sized> { |
1a4d82fc | 275 | borrow: Cell<BorrowFlag>, |
d9579d0f | 276 | value: UnsafeCell<T>, |
1a4d82fc JJ |
277 | } |
278 | ||
85aaf69f | 279 | /// An enumeration of values returned from the `state` method on a `RefCell<T>`. |
62682a34 | 280 | #[derive(Copy, Clone, PartialEq, Eq, Debug)] |
e9174d1e | 281 | #[unstable(feature = "borrow_state", issue = "27733")] |
85aaf69f SL |
282 | pub enum BorrowState { |
283 | /// The cell is currently being read, there is at least one active `borrow`. | |
284 | Reading, | |
285 | /// The cell is currently being written to, there is an active `borrow_mut`. | |
286 | Writing, | |
287 | /// There are no outstanding borrows on this cell. | |
288 | Unused, | |
289 | } | |
290 | ||
1a4d82fc | 291 | // Values [1, MAX-1] represent the number of `Ref` active |
85aaf69f SL |
292 | // (will not outgrow its range since `usize` is the size of the address space) |
293 | type BorrowFlag = usize; | |
1a4d82fc | 294 | const UNUSED: BorrowFlag = 0; |
c34b1796 | 295 | const WRITING: BorrowFlag = !0; |
1a4d82fc JJ |
296 | |
297 | impl<T> RefCell<T> { | |
85aaf69f SL |
298 | /// Creates a new `RefCell` containing `value`. |
299 | /// | |
300 | /// # Examples | |
301 | /// | |
302 | /// ``` | |
303 | /// use std::cell::RefCell; | |
304 | /// | |
305 | /// let c = RefCell::new(5); | |
306 | /// ``` | |
307 | #[stable(feature = "rust1", since = "1.0.0")] | |
c34b1796 | 308 | #[inline] |
62682a34 | 309 | pub const fn new(value: T) -> RefCell<T> { |
1a4d82fc JJ |
310 | RefCell { |
311 | value: UnsafeCell::new(value), | |
312 | borrow: Cell::new(UNUSED), | |
313 | } | |
314 | } | |
315 | ||
316 | /// Consumes the `RefCell`, returning the wrapped value. | |
85aaf69f SL |
317 | /// |
318 | /// # Examples | |
319 | /// | |
320 | /// ``` | |
321 | /// use std::cell::RefCell; | |
322 | /// | |
323 | /// let c = RefCell::new(5); | |
324 | /// | |
325 | /// let five = c.into_inner(); | |
326 | /// ``` | |
327 | #[stable(feature = "rust1", since = "1.0.0")] | |
c34b1796 | 328 | #[inline] |
1a4d82fc JJ |
329 | pub fn into_inner(self) -> T { |
330 | // Since this function takes `self` (the `RefCell`) by value, the | |
331 | // compiler statically verifies that it is not currently borrowed. | |
332 | // Therefore the following assertion is just a `debug_assert!`. | |
333 | debug_assert!(self.borrow.get() == UNUSED); | |
334 | unsafe { self.value.into_inner() } | |
335 | } | |
d9579d0f | 336 | } |
1a4d82fc | 337 | |
d9579d0f | 338 | impl<T: ?Sized> RefCell<T> { |
85aaf69f SL |
339 | /// Query the current state of this `RefCell` |
340 | /// | |
341 | /// The returned value can be dispatched on to determine if a call to | |
342 | /// `borrow` or `borrow_mut` would succeed. | |
e9174d1e | 343 | #[unstable(feature = "borrow_state", issue = "27733")] |
c34b1796 | 344 | #[inline] |
85aaf69f SL |
345 | pub fn borrow_state(&self) -> BorrowState { |
346 | match self.borrow.get() { | |
347 | WRITING => BorrowState::Writing, | |
348 | UNUSED => BorrowState::Unused, | |
349 | _ => BorrowState::Reading, | |
350 | } | |
351 | } | |
352 | ||
1a4d82fc JJ |
353 | /// Immutably borrows the wrapped value. |
354 | /// | |
355 | /// The borrow lasts until the returned `Ref` exits scope. Multiple | |
356 | /// immutable borrows can be taken out at the same time. | |
357 | /// | |
358 | /// # Panics | |
359 | /// | |
360 | /// Panics if the value is currently mutably borrowed. | |
85aaf69f SL |
361 | /// |
362 | /// # Examples | |
363 | /// | |
364 | /// ``` | |
365 | /// use std::cell::RefCell; | |
366 | /// | |
367 | /// let c = RefCell::new(5); | |
368 | /// | |
369 | /// let borrowed_five = c.borrow(); | |
370 | /// let borrowed_five2 = c.borrow(); | |
371 | /// ``` | |
372 | /// | |
373 | /// An example of panic: | |
374 | /// | |
375 | /// ``` | |
376 | /// use std::cell::RefCell; | |
377 | /// use std::thread; | |
378 | /// | |
379 | /// let result = thread::spawn(move || { | |
380 | /// let c = RefCell::new(5); | |
381 | /// let m = c.borrow_mut(); | |
382 | /// | |
383 | /// let b = c.borrow(); // this causes a panic | |
384 | /// }).join(); | |
385 | /// | |
386 | /// assert!(result.is_err()); | |
387 | /// ``` | |
388 | #[stable(feature = "rust1", since = "1.0.0")] | |
c34b1796 | 389 | #[inline] |
e9174d1e | 390 | pub fn borrow(&self) -> Ref<T> { |
85aaf69f SL |
391 | match BorrowRef::new(&self.borrow) { |
392 | Some(b) => Ref { | |
393 | _value: unsafe { &*self.value.get() }, | |
394 | _borrow: b, | |
395 | }, | |
396 | None => panic!("RefCell<T> already mutably borrowed"), | |
1a4d82fc JJ |
397 | } |
398 | } | |
399 | ||
1a4d82fc JJ |
400 | /// Mutably borrows the wrapped value. |
401 | /// | |
402 | /// The borrow lasts until the returned `RefMut` exits scope. The value | |
403 | /// cannot be borrowed while this borrow is active. | |
404 | /// | |
405 | /// # Panics | |
406 | /// | |
407 | /// Panics if the value is currently borrowed. | |
85aaf69f SL |
408 | /// |
409 | /// # Examples | |
410 | /// | |
411 | /// ``` | |
412 | /// use std::cell::RefCell; | |
413 | /// | |
414 | /// let c = RefCell::new(5); | |
415 | /// | |
416 | /// let borrowed_five = c.borrow_mut(); | |
417 | /// ``` | |
418 | /// | |
419 | /// An example of panic: | |
420 | /// | |
421 | /// ``` | |
422 | /// use std::cell::RefCell; | |
423 | /// use std::thread; | |
424 | /// | |
425 | /// let result = thread::spawn(move || { | |
426 | /// let c = RefCell::new(5); | |
bd371182 | 427 | /// let m = c.borrow(); |
85aaf69f SL |
428 | /// |
429 | /// let b = c.borrow_mut(); // this causes a panic | |
430 | /// }).join(); | |
431 | /// | |
432 | /// assert!(result.is_err()); | |
433 | /// ``` | |
434 | #[stable(feature = "rust1", since = "1.0.0")] | |
c34b1796 | 435 | #[inline] |
e9174d1e | 436 | pub fn borrow_mut(&self) -> RefMut<T> { |
85aaf69f SL |
437 | match BorrowRefMut::new(&self.borrow) { |
438 | Some(b) => RefMut { | |
439 | _value: unsafe { &mut *self.value.get() }, | |
440 | _borrow: b, | |
441 | }, | |
442 | None => panic!("RefCell<T> already borrowed"), | |
1a4d82fc JJ |
443 | } |
444 | } | |
445 | ||
62682a34 | 446 | /// Returns a reference to the underlying `UnsafeCell`. |
1a4d82fc JJ |
447 | /// |
448 | /// This can be used to circumvent `RefCell`'s safety checks. | |
449 | /// | |
450 | /// This function is `unsafe` because `UnsafeCell`'s field is public. | |
451 | #[inline] | |
e9174d1e SL |
452 | #[unstable(feature = "as_unsafe_cell", issue = "27708")] |
453 | pub unsafe fn as_unsafe_cell(&self) -> &UnsafeCell<T> { | |
1a4d82fc JJ |
454 | &self.value |
455 | } | |
456 | } | |
457 | ||
85aaf69f | 458 | #[stable(feature = "rust1", since = "1.0.0")] |
d9579d0f | 459 | unsafe impl<T: ?Sized> Send for RefCell<T> where T: Send {} |
1a4d82fc | 460 | |
85aaf69f | 461 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc | 462 | impl<T: Clone> Clone for RefCell<T> { |
c34b1796 | 463 | #[inline] |
1a4d82fc JJ |
464 | fn clone(&self) -> RefCell<T> { |
465 | RefCell::new(self.borrow().clone()) | |
466 | } | |
467 | } | |
468 | ||
85aaf69f | 469 | #[stable(feature = "rust1", since = "1.0.0")] |
1a4d82fc | 470 | impl<T:Default> Default for RefCell<T> { |
85aaf69f | 471 | #[stable(feature = "rust1", since = "1.0.0")] |
c34b1796 | 472 | #[inline] |
1a4d82fc JJ |
473 | fn default() -> RefCell<T> { |
474 | RefCell::new(Default::default()) | |
475 | } | |
476 | } | |
477 | ||
85aaf69f | 478 | #[stable(feature = "rust1", since = "1.0.0")] |
d9579d0f | 479 | impl<T: ?Sized + PartialEq> PartialEq for RefCell<T> { |
c34b1796 | 480 | #[inline] |
1a4d82fc JJ |
481 | fn eq(&self, other: &RefCell<T>) -> bool { |
482 | *self.borrow() == *other.borrow() | |
483 | } | |
484 | } | |
485 | ||
62682a34 SL |
486 | #[stable(feature = "cell_eq", since = "1.2.0")] |
487 | impl<T: ?Sized + Eq> Eq for RefCell<T> {} | |
488 | ||
1a4d82fc JJ |
489 | struct BorrowRef<'b> { |
490 | _borrow: &'b Cell<BorrowFlag>, | |
491 | } | |
492 | ||
493 | impl<'b> BorrowRef<'b> { | |
c34b1796 | 494 | #[inline] |
1a4d82fc JJ |
495 | fn new(borrow: &'b Cell<BorrowFlag>) -> Option<BorrowRef<'b>> { |
496 | match borrow.get() { | |
497 | WRITING => None, | |
498 | b => { | |
499 | borrow.set(b + 1); | |
500 | Some(BorrowRef { _borrow: borrow }) | |
501 | }, | |
502 | } | |
503 | } | |
504 | } | |
505 | ||
1a4d82fc | 506 | impl<'b> Drop for BorrowRef<'b> { |
c34b1796 | 507 | #[inline] |
1a4d82fc JJ |
508 | fn drop(&mut self) { |
509 | let borrow = self._borrow.get(); | |
510 | debug_assert!(borrow != WRITING && borrow != UNUSED); | |
511 | self._borrow.set(borrow - 1); | |
512 | } | |
513 | } | |
514 | ||
515 | impl<'b> Clone for BorrowRef<'b> { | |
c34b1796 | 516 | #[inline] |
1a4d82fc JJ |
517 | fn clone(&self) -> BorrowRef<'b> { |
518 | // Since this Ref exists, we know the borrow flag | |
519 | // is not set to WRITING. | |
520 | let borrow = self._borrow.get(); | |
521 | debug_assert!(borrow != WRITING && borrow != UNUSED); | |
522 | self._borrow.set(borrow + 1); | |
523 | BorrowRef { _borrow: self._borrow } | |
524 | } | |
525 | } | |
526 | ||
527 | /// Wraps a borrowed reference to a value in a `RefCell` box. | |
85aaf69f SL |
528 | /// A wrapper type for an immutably borrowed value from a `RefCell<T>`. |
529 | /// | |
530 | /// See the [module-level documentation](index.html) for more. | |
531 | #[stable(feature = "rust1", since = "1.0.0")] | |
d9579d0f | 532 | pub struct Ref<'b, T: ?Sized + 'b> { |
1a4d82fc JJ |
533 | // FIXME #12808: strange name to try to avoid interfering with |
534 | // field accesses of the contained type via Deref | |
535 | _value: &'b T, | |
536 | _borrow: BorrowRef<'b>, | |
537 | } | |
538 | ||
85aaf69f | 539 | #[stable(feature = "rust1", since = "1.0.0")] |
d9579d0f | 540 | impl<'b, T: ?Sized> Deref for Ref<'b, T> { |
1a4d82fc JJ |
541 | type Target = T; |
542 | ||
543 | #[inline] | |
e9174d1e | 544 | fn deref(&self) -> &T { |
1a4d82fc JJ |
545 | self._value |
546 | } | |
547 | } | |
548 | ||
62682a34 SL |
549 | impl<'b, T: ?Sized> Ref<'b, T> { |
550 | /// Copies a `Ref`. | |
551 | /// | |
552 | /// The `RefCell` is already immutably borrowed, so this cannot fail. | |
553 | /// | |
554 | /// This is an associated function that needs to be used as | |
555 | /// `Ref::clone(...)`. A `Clone` implementation or a method would interfere | |
556 | /// with the widespread use of `r.borrow().clone()` to clone the contents of | |
557 | /// a `RefCell`. | |
558 | #[unstable(feature = "cell_extras", | |
e9174d1e SL |
559 | reason = "likely to be moved to a method, pending language changes", |
560 | issue = "27746")] | |
62682a34 SL |
561 | #[inline] |
562 | pub fn clone(orig: &Ref<'b, T>) -> Ref<'b, T> { | |
563 | Ref { | |
564 | _value: orig._value, | |
565 | _borrow: orig._borrow.clone(), | |
566 | } | |
567 | } | |
568 | ||
569 | /// Make a new `Ref` for a component of the borrowed data. | |
570 | /// | |
571 | /// The `RefCell` is already immutably borrowed, so this cannot fail. | |
572 | /// | |
573 | /// This is an associated function that needs to be used as `Ref::map(...)`. | |
574 | /// A method would interfere with methods of the same name on the contents | |
575 | /// of a `RefCell` used through `Deref`. | |
576 | /// | |
577 | /// # Example | |
578 | /// | |
579 | /// ``` | |
c1a9b12d SL |
580 | /// #![feature(cell_extras)] |
581 | /// | |
62682a34 SL |
582 | /// use std::cell::{RefCell, Ref}; |
583 | /// | |
584 | /// let c = RefCell::new((5, 'b')); | |
585 | /// let b1: Ref<(u32, char)> = c.borrow(); | |
586 | /// let b2: Ref<u32> = Ref::map(b1, |t| &t.0); | |
587 | /// assert_eq!(*b2, 5) | |
588 | /// ``` | |
e9174d1e SL |
589 | #[unstable(feature = "cell_extras", reason = "recently added", |
590 | issue = "27746")] | |
62682a34 SL |
591 | #[inline] |
592 | pub fn map<U: ?Sized, F>(orig: Ref<'b, T>, f: F) -> Ref<'b, U> | |
593 | where F: FnOnce(&T) -> &U | |
594 | { | |
595 | Ref { | |
596 | _value: f(orig._value), | |
597 | _borrow: orig._borrow, | |
598 | } | |
599 | } | |
600 | ||
601 | /// Make a new `Ref` for a optional component of the borrowed data, e.g. an | |
602 | /// enum variant. | |
603 | /// | |
604 | /// The `RefCell` is already immutably borrowed, so this cannot fail. | |
605 | /// | |
606 | /// This is an associated function that needs to be used as | |
607 | /// `Ref::filter_map(...)`. A method would interfere with methods of the | |
608 | /// same name on the contents of a `RefCell` used through `Deref`. | |
609 | /// | |
610 | /// # Example | |
611 | /// | |
612 | /// ``` | |
613 | /// # #![feature(cell_extras)] | |
614 | /// use std::cell::{RefCell, Ref}; | |
615 | /// | |
616 | /// let c = RefCell::new(Ok(5)); | |
617 | /// let b1: Ref<Result<u32, ()>> = c.borrow(); | |
618 | /// let b2: Ref<u32> = Ref::filter_map(b1, |o| o.as_ref().ok()).unwrap(); | |
619 | /// assert_eq!(*b2, 5) | |
620 | /// ``` | |
e9174d1e SL |
621 | #[unstable(feature = "cell_extras", reason = "recently added", |
622 | issue = "27746")] | |
62682a34 SL |
623 | #[inline] |
624 | pub fn filter_map<U: ?Sized, F>(orig: Ref<'b, T>, f: F) -> Option<Ref<'b, U>> | |
625 | where F: FnOnce(&T) -> Option<&U> | |
626 | { | |
627 | f(orig._value).map(move |new| Ref { | |
628 | _value: new, | |
629 | _borrow: orig._borrow, | |
630 | }) | |
631 | } | |
632 | } | |
633 | ||
634 | impl<'b, T: ?Sized> RefMut<'b, T> { | |
635 | /// Make a new `RefMut` for a component of the borrowed data, e.g. an enum | |
636 | /// variant. | |
637 | /// | |
638 | /// The `RefCell` is already mutably borrowed, so this cannot fail. | |
639 | /// | |
640 | /// This is an associated function that needs to be used as | |
641 | /// `RefMut::map(...)`. A method would interfere with methods of the same | |
642 | /// name on the contents of a `RefCell` used through `Deref`. | |
643 | /// | |
644 | /// # Example | |
645 | /// | |
646 | /// ``` | |
647 | /// # #![feature(cell_extras)] | |
648 | /// use std::cell::{RefCell, RefMut}; | |
649 | /// | |
650 | /// let c = RefCell::new((5, 'b')); | |
651 | /// { | |
652 | /// let b1: RefMut<(u32, char)> = c.borrow_mut(); | |
653 | /// let mut b2: RefMut<u32> = RefMut::map(b1, |t| &mut t.0); | |
654 | /// assert_eq!(*b2, 5); | |
655 | /// *b2 = 42; | |
656 | /// } | |
657 | /// assert_eq!(*c.borrow(), (42, 'b')); | |
658 | /// ``` | |
e9174d1e SL |
659 | #[unstable(feature = "cell_extras", reason = "recently added", |
660 | issue = "27746")] | |
62682a34 SL |
661 | #[inline] |
662 | pub fn map<U: ?Sized, F>(orig: RefMut<'b, T>, f: F) -> RefMut<'b, U> | |
663 | where F: FnOnce(&mut T) -> &mut U | |
664 | { | |
665 | RefMut { | |
666 | _value: f(orig._value), | |
667 | _borrow: orig._borrow, | |
668 | } | |
669 | } | |
670 | ||
671 | /// Make a new `RefMut` for a optional component of the borrowed data, e.g. | |
672 | /// an enum variant. | |
673 | /// | |
674 | /// The `RefCell` is already mutably borrowed, so this cannot fail. | |
675 | /// | |
676 | /// This is an associated function that needs to be used as | |
677 | /// `RefMut::filter_map(...)`. A method would interfere with methods of the | |
678 | /// same name on the contents of a `RefCell` used through `Deref`. | |
679 | /// | |
680 | /// # Example | |
681 | /// | |
682 | /// ``` | |
683 | /// # #![feature(cell_extras)] | |
684 | /// use std::cell::{RefCell, RefMut}; | |
685 | /// | |
686 | /// let c = RefCell::new(Ok(5)); | |
687 | /// { | |
688 | /// let b1: RefMut<Result<u32, ()>> = c.borrow_mut(); | |
689 | /// let mut b2: RefMut<u32> = RefMut::filter_map(b1, |o| { | |
690 | /// o.as_mut().ok() | |
691 | /// }).unwrap(); | |
692 | /// assert_eq!(*b2, 5); | |
693 | /// *b2 = 42; | |
694 | /// } | |
695 | /// assert_eq!(*c.borrow(), Ok(42)); | |
696 | /// ``` | |
e9174d1e SL |
697 | #[unstable(feature = "cell_extras", reason = "recently added", |
698 | issue = "27746")] | |
62682a34 SL |
699 | #[inline] |
700 | pub fn filter_map<U: ?Sized, F>(orig: RefMut<'b, T>, f: F) -> Option<RefMut<'b, U>> | |
701 | where F: FnOnce(&mut T) -> Option<&mut U> | |
702 | { | |
703 | let RefMut { _value, _borrow } = orig; | |
704 | f(_value).map(move |new| RefMut { | |
705 | _value: new, | |
706 | _borrow: _borrow, | |
707 | }) | |
1a4d82fc JJ |
708 | } |
709 | } | |
710 | ||
711 | struct BorrowRefMut<'b> { | |
712 | _borrow: &'b Cell<BorrowFlag>, | |
713 | } | |
714 | ||
1a4d82fc | 715 | impl<'b> Drop for BorrowRefMut<'b> { |
c34b1796 | 716 | #[inline] |
1a4d82fc JJ |
717 | fn drop(&mut self) { |
718 | let borrow = self._borrow.get(); | |
719 | debug_assert!(borrow == WRITING); | |
720 | self._borrow.set(UNUSED); | |
721 | } | |
722 | } | |
723 | ||
724 | impl<'b> BorrowRefMut<'b> { | |
c34b1796 | 725 | #[inline] |
1a4d82fc JJ |
726 | fn new(borrow: &'b Cell<BorrowFlag>) -> Option<BorrowRefMut<'b>> { |
727 | match borrow.get() { | |
728 | UNUSED => { | |
729 | borrow.set(WRITING); | |
730 | Some(BorrowRefMut { _borrow: borrow }) | |
731 | }, | |
732 | _ => None, | |
733 | } | |
734 | } | |
735 | } | |
736 | ||
85aaf69f SL |
737 | /// A wrapper type for a mutably borrowed value from a `RefCell<T>`. |
738 | /// | |
739 | /// See the [module-level documentation](index.html) for more. | |
740 | #[stable(feature = "rust1", since = "1.0.0")] | |
d9579d0f | 741 | pub struct RefMut<'b, T: ?Sized + 'b> { |
1a4d82fc JJ |
742 | // FIXME #12808: strange name to try to avoid interfering with |
743 | // field accesses of the contained type via Deref | |
744 | _value: &'b mut T, | |
745 | _borrow: BorrowRefMut<'b>, | |
746 | } | |
747 | ||
85aaf69f | 748 | #[stable(feature = "rust1", since = "1.0.0")] |
d9579d0f | 749 | impl<'b, T: ?Sized> Deref for RefMut<'b, T> { |
1a4d82fc JJ |
750 | type Target = T; |
751 | ||
752 | #[inline] | |
e9174d1e | 753 | fn deref(&self) -> &T { |
1a4d82fc JJ |
754 | self._value |
755 | } | |
756 | } | |
757 | ||
85aaf69f | 758 | #[stable(feature = "rust1", since = "1.0.0")] |
d9579d0f | 759 | impl<'b, T: ?Sized> DerefMut for RefMut<'b, T> { |
1a4d82fc | 760 | #[inline] |
e9174d1e | 761 | fn deref_mut(&mut self) -> &mut T { |
1a4d82fc JJ |
762 | self._value |
763 | } | |
764 | } | |
765 | ||
766 | /// The core primitive for interior mutability in Rust. | |
767 | /// | |
85aaf69f SL |
768 | /// `UnsafeCell<T>` is a type that wraps some `T` and indicates unsafe interior operations on the |
769 | /// wrapped type. Types with an `UnsafeCell<T>` field are considered to have an 'unsafe interior'. | |
770 | /// The `UnsafeCell<T>` type is the only legal way to obtain aliasable data that is considered | |
771 | /// mutable. In general, transmuting an `&T` type into an `&mut T` is considered undefined behavior. | |
1a4d82fc | 772 | /// |
85aaf69f | 773 | /// Types like `Cell<T>` and `RefCell<T>` use this type to wrap their internal data. |
1a4d82fc | 774 | /// |
85aaf69f | 775 | /// # Examples |
1a4d82fc | 776 | /// |
85aaf69f | 777 | /// ``` |
1a4d82fc | 778 | /// use std::cell::UnsafeCell; |
85aaf69f | 779 | /// use std::marker::Sync; |
1a4d82fc JJ |
780 | /// |
781 | /// struct NotThreadSafe<T> { | |
782 | /// value: UnsafeCell<T>, | |
1a4d82fc | 783 | /// } |
85aaf69f SL |
784 | /// |
785 | /// unsafe impl<T> Sync for NotThreadSafe<T> {} | |
1a4d82fc JJ |
786 | /// ``` |
787 | /// | |
85aaf69f SL |
788 | /// **NOTE:** `UnsafeCell<T>`'s fields are public to allow static initializers. It is not |
789 | /// recommended to access its fields directly, `get` should be used instead. | |
d9579d0f | 790 | #[lang = "unsafe_cell"] |
85aaf69f | 791 | #[stable(feature = "rust1", since = "1.0.0")] |
d9579d0f | 792 | pub struct UnsafeCell<T: ?Sized> { |
e9174d1e | 793 | value: T, |
1a4d82fc JJ |
794 | } |
795 | ||
d9579d0f | 796 | impl<T: ?Sized> !Sync for UnsafeCell<T> {} |
c34b1796 | 797 | |
1a4d82fc | 798 | impl<T> UnsafeCell<T> { |
9346a6ac | 799 | /// Constructs a new instance of `UnsafeCell` which will wrap the specified |
1a4d82fc JJ |
800 | /// value. |
801 | /// | |
85aaf69f SL |
802 | /// All access to the inner value through methods is `unsafe`, and it is highly discouraged to |
803 | /// access the fields directly. | |
804 | /// | |
805 | /// # Examples | |
806 | /// | |
807 | /// ``` | |
808 | /// use std::cell::UnsafeCell; | |
809 | /// | |
810 | /// let uc = UnsafeCell::new(5); | |
811 | /// ``` | |
812 | #[stable(feature = "rust1", since = "1.0.0")] | |
c34b1796 | 813 | #[inline] |
62682a34 | 814 | pub const fn new(value: T) -> UnsafeCell<T> { |
1a4d82fc JJ |
815 | UnsafeCell { value: value } |
816 | } | |
817 | ||
d9579d0f AL |
818 | /// Unwraps the value. |
819 | /// | |
820 | /// # Unsafety | |
821 | /// | |
62682a34 SL |
822 | /// This function is unsafe because this thread or another thread may currently be |
823 | /// inspecting the inner value. | |
85aaf69f SL |
824 | /// |
825 | /// # Examples | |
826 | /// | |
827 | /// ``` | |
828 | /// use std::cell::UnsafeCell; | |
829 | /// | |
830 | /// let uc = UnsafeCell::new(5); | |
831 | /// | |
d9579d0f | 832 | /// let five = unsafe { uc.into_inner() }; |
85aaf69f | 833 | /// ``` |
1a4d82fc | 834 | #[inline] |
85aaf69f | 835 | #[stable(feature = "rust1", since = "1.0.0")] |
62682a34 | 836 | pub unsafe fn into_inner(self) -> T { |
62682a34 SL |
837 | self.value |
838 | } | |
d9579d0f | 839 | } |
1a4d82fc | 840 | |
d9579d0f AL |
841 | impl<T: ?Sized> UnsafeCell<T> { |
842 | /// Gets a mutable pointer to the wrapped value. | |
85aaf69f SL |
843 | /// |
844 | /// # Examples | |
845 | /// | |
846 | /// ``` | |
847 | /// use std::cell::UnsafeCell; | |
848 | /// | |
849 | /// let uc = UnsafeCell::new(5); | |
850 | /// | |
d9579d0f | 851 | /// let five = uc.get(); |
85aaf69f | 852 | /// ``` |
1a4d82fc | 853 | #[inline] |
85aaf69f | 854 | #[stable(feature = "rust1", since = "1.0.0")] |
d9579d0f | 855 | pub fn get(&self) -> *mut T { |
d9579d0f AL |
856 | &self.value as *const T as *mut T |
857 | } | |
1a4d82fc | 858 | } |