1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
//! # safe\_cell //! //! This crate exports the `SafeCell` type, a wrapper type that enables safe //! exterior mutability for arbitrary contents. //! //! The use case is similar to that of the standard library's //! `UnsafeCell`[¹][unsafecell] type but, by virtue of being specialized for //! situations where it can be statically proven that no unsound access //! occurs, `SafeCell` is fully usable in safe code. In addition, the //! implementation is easily proven to be fully sound, making `SafeCell` a //! great alternative to `UnsafeCell` in safety-critical code. //! //! As the implementation is incredibly lightweight and does not make use of //! any additional synchronization primitives or dynamic borrow tracking, it //! has negligible overhead (and hence functions as a true "zero-cost //! abstraction"[²][zerocost]). //! //! [unsafecell]: https://doc.rust-lang.org/std/cell/struct.UnsafeCell.html //! [zerocost]: https://boats.gitlab.io/blog/post/zero-cost-abstractions/ /// The `SafeCell` type. /// /// See the module-level documentation for more information. #[derive(Debug, Clone, Default)] pub struct SafeCell<T> { inner: T, } impl<T> SafeCell<T> { /// Returns a shared reference to the wrapped value. pub fn get(&self) -> &T { return &self.inner; } /// Returns a mutable reference to the wrapped value. /// /// Using this reference, the value can be safely mutated. Using the /// type-level mechanism provided by exterior mutability, `SafeCell` /// guarantees that no unsound concurrent access can occur. pub fn get_mut(&mut self) -> &mut T { // Safety: this is safe code. return &mut self.inner; } /// Extracts and returns the wrapped value. /// /// Note that this method must not be called concurrently, and once /// `into_inner` is called, references obtained by `get` and `get_mut` /// must no longer be used. This is statically ensured. pub fn into_inner(self) -> T { return self.inner; } /// Create a new `SafeCell`, enabling exterior mutability for the passed /// `value`. pub fn new(value: T) -> Self { return SafeCell { inner: value, }; } } #[cfg(test)] mod tests { use std::thread; use std::sync::{Arc, Mutex}; use super::*; #[test] fn basic() { let mut cell = SafeCell::new(0); assert_eq!(cell.get(), &0); *cell.get_mut() += 1; assert_eq!(cell.get(), &1); let mut other_cell = cell.clone(); *other_cell.get_mut() += 1; assert_eq!(other_cell.get(), &2); assert_eq!(cell.get(), &1); assert_eq!(cell.into_inner(), 1); } #[test] fn share() { let cell = Arc::new(Mutex::new(SafeCell::new(0))); let copy = cell.clone(); let lock = cell.lock().unwrap(); let a = { let cell = copy.clone(); thread::spawn(move || { for _ in 0..10 { *cell.lock().unwrap().get_mut() += 1; } }) }; let b = { let cell = copy.clone(); thread::spawn(move || { for _ in 0..10 { *cell.lock().unwrap().get_mut() += 2; } }) }; assert_eq!(lock.get(), &0); drop(lock); a.join().unwrap(); b.join().unwrap(); assert_eq!(cell.lock().unwrap().get(), &30); } }