1 use crate::loom::cell::UnsafeCell; 2 3 use std::rc::Rc; 4 5 /// This is exactly like `Cell<Option<Rc<T>>>`, except that it provides a `get` 6 /// method even though `Rc` is not `Copy`. 7 pub(crate) struct RcCell<T> { 8 inner: UnsafeCell<Option<Rc<T>>>, 9 } 10 11 impl<T> RcCell<T> { 12 #[cfg(not(all(loom, test)))] new() -> Self13 pub(crate) const fn new() -> Self { 14 Self { 15 inner: UnsafeCell::new(None), 16 } 17 } 18 19 // The UnsafeCell in loom does not have a const `new` fn. 20 #[cfg(all(loom, test))] new() -> Self21 pub(crate) fn new() -> Self { 22 Self { 23 inner: UnsafeCell::new(None), 24 } 25 } 26 27 /// Safety: This method may not be called recursively. 28 #[inline] with_inner<F, R>(&self, f: F) -> R where F: FnOnce(&mut Option<Rc<T>>) -> R,29 unsafe fn with_inner<F, R>(&self, f: F) -> R 30 where 31 F: FnOnce(&mut Option<Rc<T>>) -> R, 32 { 33 // safety: This type is not Sync, so concurrent calls of this method 34 // cannot happen. Furthermore, the caller guarantees that the method is 35 // not called recursively. Finally, this is the only place that can 36 // create mutable references to the inner Rc. This ensures that any 37 // mutable references created here are exclusive. 38 self.inner.with_mut(|ptr| f(&mut *ptr)) 39 } 40 get(&self) -> Option<Rc<T>>41 pub(crate) fn get(&self) -> Option<Rc<T>> { 42 // safety: The `Rc::clone` method will not call any unknown user-code, 43 // so it will not result in a recursive call to `with_inner`. 44 unsafe { self.with_inner(|rc| rc.clone()) } 45 } 46 replace(&self, val: Option<Rc<T>>) -> Option<Rc<T>>47 pub(crate) fn replace(&self, val: Option<Rc<T>>) -> Option<Rc<T>> { 48 // safety: No destructors or other unknown user-code will run inside the 49 // `with_inner` call, so no recursive call to `with_inner` can happen. 50 unsafe { self.with_inner(|rc| std::mem::replace(rc, val)) } 51 } 52 set(&self, val: Option<Rc<T>>)53 pub(crate) fn set(&self, val: Option<Rc<T>>) { 54 let old = self.replace(val); 55 drop(old); 56 } 57 } 58