mirror of
https://github.com/embassy-rs/embassy.git
synced 2025-09-27 04:10:25 +00:00
Merge pull request #4570 from U007D/sync-debug
`embassy-sync` `Debug` impls
This commit is contained in:
commit
63ade38930
@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
## Unreleased
|
||||
|
||||
- Add `get_mut` to `LazyLock`
|
||||
- Add more `Debug` impls to `embassy-sync`, particularly on `OnceLock`
|
||||
|
||||
## 0.7.0 - 2025-05-28
|
||||
|
||||
|
@ -22,6 +22,7 @@ use self::raw::RawMutex;
|
||||
///
|
||||
/// In all cases, the blocking mutex is intended to be short lived and not held across await points.
|
||||
/// Use the async [`Mutex`](crate::mutex::Mutex) if you need a lock that is held across await points.
|
||||
#[derive(Debug)]
|
||||
pub struct Mutex<R, T: ?Sized> {
|
||||
// NOTE: `raw` must be FIRST, so when using ThreadModeMutex the "can't drop in non-thread-mode" gets
|
||||
// to run BEFORE dropping `data`.
|
||||
|
@ -37,6 +37,7 @@ pub unsafe trait RawMutex {
|
||||
/// # Safety
|
||||
///
|
||||
/// This mutex is safe to share between different executors and interrupts.
|
||||
#[derive(Debug)]
|
||||
pub struct CriticalSectionRawMutex {
|
||||
_phantom: PhantomData<()>,
|
||||
}
|
||||
@ -65,6 +66,7 @@ unsafe impl RawMutex for CriticalSectionRawMutex {
|
||||
/// # Safety
|
||||
///
|
||||
/// **This Mutex is only safe within a single executor.**
|
||||
#[derive(Debug)]
|
||||
pub struct NoopRawMutex {
|
||||
_phantom: PhantomData<*mut ()>,
|
||||
}
|
||||
|
@ -55,6 +55,7 @@ use crate::blocking_mutex::Mutex;
|
||||
use crate::waitqueue::WakerRegistration;
|
||||
|
||||
/// Send-only access to a [`Channel`].
|
||||
#[derive(Debug)]
|
||||
pub struct Sender<'ch, M, T, const N: usize>
|
||||
where
|
||||
M: RawMutex,
|
||||
@ -241,6 +242,7 @@ impl<'ch, T> SendDynamicSender<'ch, T> {
|
||||
}
|
||||
|
||||
/// Receive-only access to a [`Channel`].
|
||||
#[derive(Debug)]
|
||||
pub struct Receiver<'ch, M, T, const N: usize>
|
||||
where
|
||||
M: RawMutex,
|
||||
@ -486,6 +488,7 @@ where
|
||||
|
||||
/// Future returned by [`Channel::receive`] and [`Receiver::receive`].
|
||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||
#[derive(Debug)]
|
||||
pub struct ReceiveFuture<'ch, M, T, const N: usize>
|
||||
where
|
||||
M: RawMutex,
|
||||
@ -506,6 +509,7 @@ where
|
||||
|
||||
/// Future returned by [`Channel::ready_to_receive`] and [`Receiver::ready_to_receive`].
|
||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||
#[derive(Debug)]
|
||||
pub struct ReceiveReadyFuture<'ch, M, T, const N: usize>
|
||||
where
|
||||
M: RawMutex,
|
||||
@ -549,6 +553,7 @@ impl<'ch, M: RawMutex, T, const N: usize> From<ReceiveFuture<'ch, M, T, N>> for
|
||||
|
||||
/// Future returned by [`Channel::send`] and [`Sender::send`].
|
||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||
#[derive(Debug)]
|
||||
pub struct SendFuture<'ch, M, T, const N: usize>
|
||||
where
|
||||
M: RawMutex,
|
||||
@ -646,6 +651,7 @@ pub enum TrySendError<T> {
|
||||
Full(T),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct ChannelState<T, const N: usize> {
|
||||
queue: Deque<T, N>,
|
||||
receiver_waker: WakerRegistration,
|
||||
@ -785,6 +791,7 @@ impl<T, const N: usize> ChannelState<T, N> {
|
||||
/// received from the channel.
|
||||
///
|
||||
/// All data sent will become available in the same order as it was sent.
|
||||
#[derive(Debug)]
|
||||
pub struct Channel<M, T, const N: usize>
|
||||
where
|
||||
M: RawMutex,
|
||||
|
@ -21,6 +21,7 @@ use core::sync::atomic::{AtomicBool, Ordering};
|
||||
/// let reference = VALUE.get();
|
||||
/// assert_eq!(reference, &20);
|
||||
/// ```
|
||||
#[derive(Debug)]
|
||||
pub struct LazyLock<T, F = fn() -> T> {
|
||||
init: AtomicBool,
|
||||
data: UnsafeCell<Data<T, F>>,
|
||||
@ -144,6 +145,7 @@ mod tests {
|
||||
}
|
||||
|
||||
static DROP_CHECKER: AtomicU32 = AtomicU32::new(0);
|
||||
#[derive(Debug)]
|
||||
struct DropCheck;
|
||||
|
||||
impl Drop for DropCheck {
|
||||
|
@ -16,6 +16,7 @@ use crate::waitqueue::WakerRegistration;
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub struct TryLockError;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct State {
|
||||
locked: bool,
|
||||
waker: WakerRegistration,
|
||||
|
@ -1,6 +1,7 @@
|
||||
//! Synchronization primitive for initializing a value once, allowing others to await a reference to the value.
|
||||
|
||||
use core::cell::Cell;
|
||||
use core::fmt::{Debug, Formatter};
|
||||
use core::future::{poll_fn, Future};
|
||||
use core::mem::MaybeUninit;
|
||||
use core::sync::atomic::{AtomicBool, Ordering};
|
||||
@ -42,6 +43,15 @@ pub struct OnceLock<T> {
|
||||
data: Cell<MaybeUninit<T>>,
|
||||
}
|
||||
|
||||
impl<T> Debug for OnceLock<T> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
|
||||
f.debug_struct("OnceLock")
|
||||
.field("init", &self.init)
|
||||
.field("data", &"Cell<MaybeUninit<{unprintable}>>")
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<T> Sync for OnceLock<T> where T: Sync {}
|
||||
|
||||
impl<T> OnceLock<T> {
|
||||
|
@ -13,6 +13,7 @@ use crate::ring_buffer::RingBuffer;
|
||||
use crate::waitqueue::WakerRegistration;
|
||||
|
||||
/// Write-only access to a [`Pipe`].
|
||||
#[derive(Debug)]
|
||||
pub struct Writer<'p, M, const N: usize>
|
||||
where
|
||||
M: RawMutex,
|
||||
@ -52,6 +53,7 @@ where
|
||||
|
||||
/// Future returned by [`Pipe::write`] and [`Writer::write`].
|
||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||
#[derive(Debug)]
|
||||
pub struct WriteFuture<'p, M, const N: usize>
|
||||
where
|
||||
M: RawMutex,
|
||||
@ -77,6 +79,7 @@ where
|
||||
impl<'p, M, const N: usize> Unpin for WriteFuture<'p, M, N> where M: RawMutex {}
|
||||
|
||||
/// Read-only access to a [`Pipe`].
|
||||
#[derive(Debug)]
|
||||
pub struct Reader<'p, M, const N: usize>
|
||||
where
|
||||
M: RawMutex,
|
||||
@ -128,6 +131,7 @@ where
|
||||
|
||||
/// Future returned by [`Pipe::read`] and [`Reader::read`].
|
||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||
#[derive(Debug)]
|
||||
pub struct ReadFuture<'p, M, const N: usize>
|
||||
where
|
||||
M: RawMutex,
|
||||
@ -154,6 +158,7 @@ impl<'p, M, const N: usize> Unpin for ReadFuture<'p, M, N> where M: RawMutex {}
|
||||
|
||||
/// Future returned by [`Reader::fill_buf`].
|
||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||
#[derive(Debug)]
|
||||
pub struct FillBufFuture<'p, M, const N: usize>
|
||||
where
|
||||
M: RawMutex,
|
||||
@ -199,6 +204,7 @@ pub enum TryWriteError {
|
||||
Full,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct PipeState<const N: usize> {
|
||||
buffer: RingBuffer<N>,
|
||||
read_waker: WakerRegistration,
|
||||
@ -206,6 +212,7 @@ struct PipeState<const N: usize> {
|
||||
}
|
||||
|
||||
#[repr(transparent)]
|
||||
#[derive(Debug)]
|
||||
struct Buffer<const N: usize>(UnsafeCell<[u8; N]>);
|
||||
|
||||
impl<const N: usize> Buffer<N> {
|
||||
@ -230,6 +237,7 @@ unsafe impl<const N: usize> Sync for Buffer<N> {}
|
||||
/// buffer is full, attempts to `write` new bytes will wait until buffer space is freed up.
|
||||
///
|
||||
/// All data written will become available in the same order as it was written.
|
||||
#[derive(Debug)]
|
||||
pub struct Pipe<M, const N: usize>
|
||||
where
|
||||
M: RawMutex,
|
||||
|
@ -71,6 +71,7 @@ pub use subscriber::{DynSubscriber, Subscriber};
|
||||
/// # block_on(test);
|
||||
/// ```
|
||||
///
|
||||
#[derive(Debug)]
|
||||
pub struct PubSubChannel<M: RawMutex, T: Clone, const CAP: usize, const SUBS: usize, const PUBS: usize> {
|
||||
inner: Mutex<M, RefCell<PubSubState<T, CAP, SUBS, PUBS>>>,
|
||||
}
|
||||
@ -297,6 +298,7 @@ impl<M: RawMutex, T: Clone, const CAP: usize, const SUBS: usize, const PUBS: usi
|
||||
}
|
||||
|
||||
/// Internal state for the PubSub channel
|
||||
#[derive(Debug)]
|
||||
struct PubSubState<T: Clone, const CAP: usize, const SUBS: usize, const PUBS: usize> {
|
||||
/// The queue contains the last messages that have been published and a countdown of how many subscribers are yet to read it
|
||||
queue: Deque<(T, usize), CAP>,
|
||||
|
@ -10,6 +10,7 @@ use super::{PubSubBehavior, PubSubChannel};
|
||||
use crate::blocking_mutex::raw::RawMutex;
|
||||
|
||||
/// A publisher to a channel
|
||||
#[derive(Debug)]
|
||||
pub struct Pub<'a, PSB: PubSubBehavior<T> + ?Sized, T: Clone> {
|
||||
/// The channel we are a publisher for
|
||||
channel: &'a PSB,
|
||||
@ -106,6 +107,7 @@ impl<'a, T: Clone> DerefMut for DynPublisher<'a, T> {
|
||||
}
|
||||
|
||||
/// A publisher that holds a generic reference to the channel
|
||||
#[derive(Debug)]
|
||||
pub struct Publisher<'a, M: RawMutex, T: Clone, const CAP: usize, const SUBS: usize, const PUBS: usize>(
|
||||
pub(super) Pub<'a, PubSubChannel<M, T, CAP, SUBS, PUBS>, T>,
|
||||
);
|
||||
@ -130,6 +132,7 @@ impl<'a, M: RawMutex, T: Clone, const CAP: usize, const SUBS: usize, const PUBS:
|
||||
|
||||
/// A publisher that can only use the `publish_immediate` function, but it doesn't have to be registered with the channel.
|
||||
/// (So an infinite amount is possible)
|
||||
#[derive(Debug)]
|
||||
pub struct ImmediatePub<'a, PSB: PubSubBehavior<T> + ?Sized, T: Clone> {
|
||||
/// The channel we are a publisher for
|
||||
channel: &'a PSB,
|
||||
@ -205,6 +208,7 @@ impl<'a, T: Clone> DerefMut for DynImmediatePublisher<'a, T> {
|
||||
}
|
||||
|
||||
/// An immediate publisher that holds a generic reference to the channel
|
||||
#[derive(Debug)]
|
||||
pub struct ImmediatePublisher<'a, M: RawMutex, T: Clone, const CAP: usize, const SUBS: usize, const PUBS: usize>(
|
||||
pub(super) ImmediatePub<'a, PubSubChannel<M, T, CAP, SUBS, PUBS>, T>,
|
||||
);
|
||||
@ -229,6 +233,7 @@ impl<'a, M: RawMutex, T: Clone, const CAP: usize, const SUBS: usize, const PUBS:
|
||||
|
||||
#[must_use = "Sinks do nothing unless polled"]
|
||||
/// [`futures_sink::Sink`] adapter for [`Pub`].
|
||||
#[derive(Debug)]
|
||||
pub struct PubSink<'a, 'p, PSB, T>
|
||||
where
|
||||
T: Clone,
|
||||
@ -290,6 +295,7 @@ where
|
||||
|
||||
/// Future for the publisher wait action
|
||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||
#[derive(Debug)]
|
||||
pub struct PublisherWaitFuture<'s, 'a, PSB: PubSubBehavior<T> + ?Sized, T: Clone> {
|
||||
/// The message we need to publish
|
||||
message: Option<T>,
|
||||
|
@ -10,6 +10,7 @@ use super::{PubSubBehavior, PubSubChannel, WaitResult};
|
||||
use crate::blocking_mutex::raw::RawMutex;
|
||||
|
||||
/// A subscriber to a channel
|
||||
#[derive(Debug)]
|
||||
pub struct Sub<'a, PSB: PubSubBehavior<T> + ?Sized, T: Clone> {
|
||||
/// The message id of the next message we are yet to receive
|
||||
next_message_id: u64,
|
||||
@ -151,6 +152,7 @@ impl<'a, T: Clone> DerefMut for DynSubscriber<'a, T> {
|
||||
}
|
||||
|
||||
/// A subscriber that holds a generic reference to the channel
|
||||
#[derive(Debug)]
|
||||
pub struct Subscriber<'a, M: RawMutex, T: Clone, const CAP: usize, const SUBS: usize, const PUBS: usize>(
|
||||
pub(super) Sub<'a, PubSubChannel<M, T, CAP, SUBS, PUBS>, T>,
|
||||
);
|
||||
@ -175,6 +177,7 @@ impl<'a, M: RawMutex, T: Clone, const CAP: usize, const SUBS: usize, const PUBS:
|
||||
|
||||
/// Future for the subscriber wait action
|
||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||
#[derive(Debug)]
|
||||
pub struct SubscriberWaitFuture<'s, 'a, PSB: PubSubBehavior<T> + ?Sized, T: Clone> {
|
||||
subscriber: &'s mut Sub<'a, PSB, T>,
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
use core::ops::Range;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct RingBuffer<const N: usize> {
|
||||
start: usize,
|
||||
end: usize,
|
||||
|
@ -16,6 +16,7 @@ use crate::waitqueue::WakerRegistration;
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub struct TryLockError;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct State {
|
||||
readers: usize,
|
||||
writer: bool,
|
||||
|
@ -46,6 +46,7 @@ pub trait Semaphore: Sized {
|
||||
/// A representation of a number of acquired permits.
|
||||
///
|
||||
/// The acquired permits will be released back to the [`Semaphore`] when this is dropped.
|
||||
#[derive(Debug)]
|
||||
pub struct SemaphoreReleaser<'a, S: Semaphore> {
|
||||
semaphore: &'a S,
|
||||
permits: usize,
|
||||
@ -181,6 +182,7 @@ impl<M: RawMutex> Semaphore for GreedySemaphore<M> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct SemaphoreState {
|
||||
permits: usize,
|
||||
waker: WakerRegistration,
|
||||
@ -221,6 +223,7 @@ impl SemaphoreState {
|
||||
///
|
||||
/// Up to `N` tasks may attempt to acquire permits concurrently. If additional
|
||||
/// tasks attempt to acquire a permit, a [`WaitQueueFull`] error will be returned.
|
||||
#[derive(Debug)]
|
||||
pub struct FairSemaphore<M, const N: usize>
|
||||
where
|
||||
M: RawMutex,
|
||||
@ -341,6 +344,7 @@ impl<M: RawMutex, const N: usize> Semaphore for FairSemaphore<M, N> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct FairAcquire<'a, M: RawMutex, const N: usize> {
|
||||
sema: &'a FairSemaphore<M, N>,
|
||||
permits: usize,
|
||||
@ -364,6 +368,7 @@ impl<'a, M: RawMutex, const N: usize> core::future::Future for FairAcquire<'a, M
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct FairAcquireAll<'a, M: RawMutex, const N: usize> {
|
||||
sema: &'a FairSemaphore<M, N>,
|
||||
min: usize,
|
||||
@ -387,6 +392,7 @@ impl<'a, M: RawMutex, const N: usize> core::future::Future for FairAcquireAll<'a
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct FairSemaphoreState<const N: usize> {
|
||||
permits: usize,
|
||||
next_ticket: usize,
|
||||
|
@ -39,6 +39,7 @@ where
|
||||
state: Mutex<M, Cell<State<T>>>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum State<T> {
|
||||
None,
|
||||
Waiting(Waker),
|
||||
|
@ -7,6 +7,7 @@ use core::task::Waker;
|
||||
/// If a waker is registered, registering another waker will replace the previous one without waking it.
|
||||
/// The intended use case is to wake tasks from interrupts. Therefore, it is generally not expected,
|
||||
/// that multiple tasks register try to register a waker simultaneously.
|
||||
#[derive(Debug)]
|
||||
pub struct AtomicWaker {
|
||||
waker: AtomicPtr<()>,
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ use heapless::Vec;
|
||||
/// Utility struct to register and wake multiple wakers.
|
||||
/// Queue of wakers with a maximum length of `N`.
|
||||
/// Intended for waking multiple tasks.
|
||||
#[derive(Debug)]
|
||||
pub struct MultiWakerRegistration<const N: usize> {
|
||||
wakers: Vec<Waker, N>,
|
||||
}
|
||||
|
@ -65,10 +65,12 @@ use crate::waitqueue::MultiWakerRegistration;
|
||||
/// };
|
||||
/// block_on(f);
|
||||
/// ```
|
||||
#[derive(Debug)]
|
||||
pub struct Watch<M: RawMutex, T: Clone, const N: usize> {
|
||||
mutex: Mutex<M, RefCell<WatchState<T, N>>>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct WatchState<T: Clone, const N: usize> {
|
||||
data: Option<T>,
|
||||
current_id: u64,
|
||||
@ -392,6 +394,7 @@ impl<M: RawMutex, T: Clone, const N: usize> Watch<M, T, N> {
|
||||
}
|
||||
|
||||
/// A receiver can `.await` a change in the `Watch` value.
|
||||
#[derive(Debug)]
|
||||
pub struct Snd<'a, T: Clone, W: WatchBehavior<T> + ?Sized> {
|
||||
watch: &'a W,
|
||||
_phantom: PhantomData<T>,
|
||||
@ -467,6 +470,7 @@ impl<'a, T: Clone, W: WatchBehavior<T> + ?Sized> Snd<'a, T, W> {
|
||||
///
|
||||
/// For a simpler type definition, consider [`DynSender`] at the expense of
|
||||
/// some runtime performance due to dynamic dispatch.
|
||||
#[derive(Debug)]
|
||||
pub struct Sender<'a, M: RawMutex, T: Clone, const N: usize>(Snd<'a, T, Watch<M, T, N>>);
|
||||
|
||||
impl<'a, M: RawMutex, T: Clone, const N: usize> Clone for Sender<'a, M, T, N> {
|
||||
@ -622,6 +626,7 @@ impl<'a, T: Clone, W: WatchBehavior<T> + ?Sized> Drop for Rcv<'a, T, W> {
|
||||
}
|
||||
|
||||
/// A anonymous receiver can NOT `.await` a change in the `Watch` value.
|
||||
#[derive(Debug)]
|
||||
pub struct AnonRcv<'a, T: Clone, W: WatchBehavior<T> + ?Sized> {
|
||||
watch: &'a W,
|
||||
at_id: u64,
|
||||
@ -726,6 +731,7 @@ impl<'a, T: Clone> DerefMut for DynReceiver<'a, T> {
|
||||
}
|
||||
|
||||
/// A receiver of a `Watch` channel that cannot `.await` values.
|
||||
#[derive(Debug)]
|
||||
pub struct AnonReceiver<'a, M: RawMutex, T: Clone, const N: usize>(AnonRcv<'a, T, Watch<M, T, N>>);
|
||||
|
||||
impl<'a, M: RawMutex, T: Clone, const N: usize> AnonReceiver<'a, M, T, N> {
|
||||
|
@ -34,6 +34,7 @@ use crate::waitqueue::WakerRegistration;
|
||||
///
|
||||
/// The channel requires a buffer of recyclable elements. Writing to the channel is done through
|
||||
/// an `&mut T`.
|
||||
#[derive(Debug)]
|
||||
pub struct Channel<'a, M: RawMutex, T> {
|
||||
buf: BufferPtr<T>,
|
||||
phantom: PhantomData<&'a mut T>,
|
||||
@ -95,6 +96,7 @@ impl<'a, M: RawMutex, T> Channel<'a, M, T> {
|
||||
}
|
||||
|
||||
#[repr(transparent)]
|
||||
#[derive(Debug)]
|
||||
struct BufferPtr<T>(*mut T);
|
||||
|
||||
impl<T> BufferPtr<T> {
|
||||
@ -107,6 +109,7 @@ unsafe impl<T> Send for BufferPtr<T> {}
|
||||
unsafe impl<T> Sync for BufferPtr<T> {}
|
||||
|
||||
/// Send-only access to a [`Channel`].
|
||||
#[derive(Debug)]
|
||||
pub struct Sender<'a, M: RawMutex, T> {
|
||||
channel: &'a Channel<'a, M, T>,
|
||||
}
|
||||
@ -190,6 +193,7 @@ impl<'a, M: RawMutex, T> Sender<'a, M, T> {
|
||||
}
|
||||
|
||||
/// Receive-only access to a [`Channel`].
|
||||
#[derive(Debug)]
|
||||
pub struct Receiver<'a, M: RawMutex, T> {
|
||||
channel: &'a Channel<'a, M, T>,
|
||||
}
|
||||
@ -272,6 +276,7 @@ impl<'a, M: RawMutex, T> Receiver<'a, M, T> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct State {
|
||||
/// Maximum number of elements the channel can hold.
|
||||
capacity: usize,
|
||||
|
Loading…
x
Reference in New Issue
Block a user