aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--rtic-sync/src/channel.rs7
-rw-r--r--rtic-sync/src/unsafecell.rs81
2 files changed, 57 insertions, 31 deletions
diff --git a/rtic-sync/src/channel.rs b/rtic-sync/src/channel.rs
index 043d058..f2f8aa1 100644
--- a/rtic-sync/src/channel.rs
+++ b/rtic-sync/src/channel.rs
@@ -104,9 +104,7 @@ impl<T, const N: usize> Channel<T, N> {
/// Split the queue into a `Sender`/`Receiver` pair.
pub fn split(&mut self) -> (Sender<'_, T, N>, Receiver<'_, T, N>) {
- // SAFETY: we have exclusive access to `self`.
- let freeq = self.freeq.get_mut();
- let freeq = unsafe { freeq.deref() };
+ let freeq = self.freeq.as_mut();
// Fill free queue
for idx in 0..N as u8 {
@@ -123,8 +121,7 @@ impl<T, const N: usize> Channel<T, N> {
debug_assert!(freeq.is_full());
// There is now 1 sender
- // SAFETY: we have exclusive access to `self`.
- unsafe { *self.num_senders.get_mut().deref() = 1 };
+ *self.num_senders.as_mut() = 1;
(Sender(self), Receiver(self))
}
diff --git a/rtic-sync/src/unsafecell.rs b/rtic-sync/src/unsafecell.rs
index e3730d4..707f413 100644
--- a/rtic-sync/src/unsafecell.rs
+++ b/rtic-sync/src/unsafecell.rs
@@ -1,39 +1,68 @@
//! Compat layer for [`core::cell::UnsafeCell`] and `loom::cell::UnsafeCell`.
#[cfg(loom)]
-pub use loom::cell::UnsafeCell;
+use loom::cell::UnsafeCell as InnerUnsafeCell;
-#[cfg(not(loom))]
-pub use core::UnsafeCell;
+#[cfg(loom)]
+pub use loom::cell::MutPtr;
#[cfg(not(loom))]
-mod core {
- /// An [`core::cell::UnsafeCell`] wrapper that provides compatibility with
- /// loom's UnsafeCell.
- #[derive(Debug)]
- pub struct UnsafeCell<T>(core::cell::UnsafeCell<T>);
-
- impl<T> UnsafeCell<T> {
- /// Create a new `UnsafeCell`.
- pub const fn new(data: T) -> UnsafeCell<T> {
- UnsafeCell(core::cell::UnsafeCell::new(data))
- }
+use core::cell::UnsafeCell as InnerUnsafeCell;
- /// Access the contents of the `UnsafeCell` through a mut pointer.
- pub fn get_mut(&self) -> MutPtr<T> {
- MutPtr(self.0.get())
- }
+/// An [`core::cell::UnsafeCell`] wrapper that provides compatibility with
+/// loom's UnsafeCell.
+#[derive(Debug)]
+pub struct UnsafeCell<T>(InnerUnsafeCell<T>);
+
+impl<T> UnsafeCell<T> {
+ /// Create a new `UnsafeCell`.
+ #[cfg(not(loom))]
+ pub const fn new(data: T) -> UnsafeCell<T> {
+ UnsafeCell(InnerUnsafeCell::new(data))
}
- pub struct MutPtr<T>(*mut T);
+ #[cfg(loom)]
+ pub fn new(data: T) -> UnsafeCell<T> {
+ UnsafeCell(InnerUnsafeCell::new(data))
+ }
+
+ /// Access the contents of the `UnsafeCell` through a tracked mut pointer.
+ pub fn get_mut(&self) -> MutPtr<T> {
+ #[cfg(loom)]
+ return self.0.get_mut();
+
+ #[cfg(not(loom))]
+ return MutPtr(self.0.get());
+ }
- impl<T> MutPtr<T> {
- #[allow(clippy::mut_from_ref)]
- /// SAFETY: the caller must guarantee that the contained `*mut T` is not
- /// null, and must uphold the same safety requirements as for
- /// [`core::primitive::pointer::as_mut`] for the contained `*mut T`.
- pub unsafe fn deref(&self) -> &mut T {
- &mut *self.0
+ /// Access the contents of the `UnsafeCell` mutably.
+ pub fn as_mut(&mut self) -> &mut T {
+ #[cfg(not(loom))]
+ return self.0.get_mut();
+
+ #[cfg(loom)]
+ {
+ // SAFETY: we have exclusive access to `self`.
+ let ptr = self.get_mut();
+ let ptr = unsafe { ptr.deref() };
+
+ // SAFETY: we have exclusive access to `self` for the duration of
+ // the borrow.
+ unsafe { core::mem::transmute(ptr) }
}
}
}
+
+#[cfg(not(loom))]
+pub struct MutPtr<T>(*mut T);
+
+#[cfg(not(loom))]
+impl<T> MutPtr<T> {
+ #[allow(clippy::mut_from_ref)]
+ /// SAFETY: the caller must guarantee that the contained `*mut T` is not
+ /// null, and must uphold the same safety requirements as for
+ /// [`core::primitive::pointer::as_mut`] for the contained `*mut T`.
+ pub unsafe fn deref(&self) -> &mut T {
+ &mut *self.0
+ }
+}