rtic_sync/
unsafecell.rs

1//! Compat layer for [`core::cell::UnsafeCell`] and `loom::cell::UnsafeCell`.
2
3#[cfg(loom)]
4use loom::cell::UnsafeCell as InnerUnsafeCell;
5
6#[cfg(loom)]
7pub use loom::cell::MutPtr;
8
9#[cfg(not(loom))]
10use core::cell::UnsafeCell as InnerUnsafeCell;
11
12/// An [`core::cell::UnsafeCell`] wrapper that provides compatibility with
13/// loom's UnsafeCell.
14#[derive(Debug)]
15pub struct UnsafeCell<T>(InnerUnsafeCell<T>);
16
17impl<T> UnsafeCell<T> {
18    /// Create a new `UnsafeCell`.
19    #[cfg(not(loom))]
20    pub const fn new(data: T) -> UnsafeCell<T> {
21        UnsafeCell(InnerUnsafeCell::new(data))
22    }
23
24    #[cfg(loom)]
25    pub fn new(data: T) -> UnsafeCell<T> {
26        UnsafeCell(InnerUnsafeCell::new(data))
27    }
28
29    /// Access the contents of the `UnsafeCell` through a tracked mut pointer.
30    pub fn get_mut(&self) -> MutPtr<T> {
31        #[cfg(loom)]
32        return self.0.get_mut();
33
34        #[cfg(not(loom))]
35        return MutPtr(self.0.get());
36    }
37
38    /// Access the contents of the `UnsafeCell` mutably.
39    pub fn as_mut(&mut self) -> &mut T {
40        #[cfg(not(loom))]
41        return self.0.get_mut();
42
43        #[cfg(loom)]
44        {
45            // SAFETY: we have exclusive access to `self`.
46            let ptr = self.get_mut();
47            let ptr = unsafe { ptr.deref() };
48
49            // SAFETY: we have exclusive access to `self` for the duration of
50            // the borrow.
51            unsafe { core::mem::transmute(ptr) }
52        }
53    }
54}
55
56#[cfg(not(loom))]
57pub struct MutPtr<T>(*mut T);
58
59#[cfg(not(loom))]
60impl<T> MutPtr<T> {
61    #[allow(clippy::mut_from_ref)]
62    /// SAFETY: the caller must guarantee that the contained `*mut T` is not
63    /// null, and must uphold the same safety requirements as for
64    /// [`core::primitive::pointer::as_mut`] for the contained `*mut T`.
65    pub unsafe fn deref(&self) -> &mut T {
66        &mut *self.0
67    }
68}