Remove Q* type aliases for MpMcQueue, and rename it to just Queue

This commit is contained in:
Christian Poveda 2025-04-04 15:53:51 -05:00
parent a849a60067
commit b6d10f62fe
No known key found for this signature in database
GPG Key ID: 3B422F347D81A9E8
3 changed files with 49 additions and 67 deletions

View File

@ -17,9 +17,9 @@
//! use cortex_m::{asm, peripheral::syst::SystClkSource}; //! use cortex_m::{asm, peripheral::syst::SystClkSource};
//! use cortex_m_rt::{entry, exception}; //! use cortex_m_rt::{entry, exception};
//! use cortex_m_semihosting::hprintln; //! use cortex_m_semihosting::hprintln;
//! use heapless::mpmc::Q2; //! use heapless::mpmc::Queue::<_, 2>;
//! //!
//! static Q: Q2<u8> = Q2::new(); //! static Q: Queue::<_, 2><u8> = Q2::new();
//! //!
//! #[entry] //! #[entry]
//! fn main() -> ! { //! fn main() -> ! {
@ -112,29 +112,11 @@ type IntSize = isize;
#[cfg(not(feature = "mpmc_large"))] #[cfg(not(feature = "mpmc_large"))]
type IntSize = i8; type IntSize = i8;
/// MPMC queue with a capability for 2 elements. /// Base struct for [`Queue`] and [`QueueView`], generic over the [`Storage`].
pub type Q2<T> = MpMcQueue<T, 2>;
/// MPMC queue with a capability for 4 elements.
pub type Q4<T> = MpMcQueue<T, 4>;
/// MPMC queue with a capability for 8 elements.
pub type Q8<T> = MpMcQueue<T, 8>;
/// MPMC queue with a capability for 16 elements.
pub type Q16<T> = MpMcQueue<T, 16>;
/// MPMC queue with a capability for 32 elements.
pub type Q32<T> = MpMcQueue<T, 32>;
/// MPMC queue with a capability for 64 elements.
pub type Q64<T> = MpMcQueue<T, 64>;
/// Base struct for [`MpMcQueue`] and [`MpMcQueueView`], generic over the [`Storage`].
/// ///
/// In most cases you should use [`MpMcQueue`] or [`MpMcQueueView`] directly. Only use this /// In most cases you should use [`Queue`] or [`QueueView`] directly. Only use this
/// struct if you want to write code that's generic over both. /// struct if you want to write code that's generic over both.
pub struct MpMcQueueInner<T, S: Storage> { pub struct QueueInner<T, S: Storage> {
dequeue_pos: AtomicTargetSize, dequeue_pos: AtomicTargetSize,
enqueue_pos: AtomicTargetSize, enqueue_pos: AtomicTargetSize,
buffer: UnsafeCell<S::Buffer<Cell<T>>>, buffer: UnsafeCell<S::Buffer<Cell<T>>>,
@ -143,14 +125,14 @@ pub struct MpMcQueueInner<T, S: Storage> {
/// MPMC queue with a capacity for N elements /// MPMC queue with a capacity for N elements
/// N must be a power of 2 /// N must be a power of 2
/// The max value of N is `u8::MAX` - 1 if `mpmc_large` feature is not enabled. /// The max value of N is `u8::MAX` - 1 if `mpmc_large` feature is not enabled.
pub type MpMcQueue<T, const N: usize> = MpMcQueueInner<T, OwnedStorage<N>>; pub type Queue<T, const N: usize> = QueueInner<T, OwnedStorage<N>>;
/// MPMC queue with a capacity for N elements /// MPMC queue with a capacity for N elements
/// N must be a power of 2 /// N must be a power of 2
/// The max value of N is `u8::MAX` - 1 if `mpmc_large` feature is not enabled. /// The max value of N is `u8::MAX` - 1 if `mpmc_large` feature is not enabled.
pub type MpMcQueueView<T> = MpMcQueueInner<T, ViewStorage>; pub type QueueView<T> = QueueInner<T, ViewStorage>;
impl<T, const N: usize> MpMcQueue<T, N> { impl<T, const N: usize> Queue<T, N> {
/// Creates an empty queue /// Creates an empty queue
pub const fn new() -> Self { pub const fn new() -> Self {
const { const {
@ -175,54 +157,54 @@ impl<T, const N: usize> MpMcQueue<T, N> {
} }
/// Used in `Storage` implementation /// Used in `Storage` implementation
pub(crate) fn as_view_private(&self) -> &MpMcQueueView<T> { pub(crate) fn as_view_private(&self) -> &QueueView<T> {
self self
} }
/// Used in `Storage` implementation /// Used in `Storage` implementation
pub(crate) fn as_view_mut_private(&mut self) -> &mut MpMcQueueView<T> { pub(crate) fn as_view_mut_private(&mut self) -> &mut QueueView<T> {
self self
} }
} }
impl<T, S: Storage> MpMcQueueInner<T, S> { impl<T, S: Storage> QueueInner<T, S> {
/// Get a reference to the `MpMcQueue`, erasing the `N` const-generic. /// Get a reference to the `Queue`, erasing the `N` const-generic.
/// ///
/// ///
/// ```rust /// ```rust
/// # use heapless::mpmc::{MpMcQueue, MpMcQueueView}; /// # use heapless::mpmc::{Queue, QueueView};
/// let queue: MpMcQueue<u8, 2> = MpMcQueue::new(); /// let queue: Queue<u8, 2> = Queue::new();
/// let view: &MpMcQueueView<u8> = queue.as_view(); /// let view: &QueueView<u8> = queue.as_view();
/// ``` /// ```
/// ///
/// It is often preferable to do the same through type coerction, since `MpMcQueue<T, N>` implements `Unsize<MpMcQueueView<T>>`: /// It is often preferable to do the same through type coerction, since `Queue<T, N>` implements `Unsize<QueueView<T>>`:
/// ///
/// ```rust /// ```rust
/// # use heapless::mpmc::{MpMcQueue, MpMcQueueView}; /// # use heapless::mpmc::{Queue, QueueView};
/// let queue: MpMcQueue<u8, 2> = MpMcQueue::new(); /// let queue: Queue<u8, 2> = Queue::new();
/// let view: &MpMcQueueView<u8> = &queue; /// let view: &QueueView<u8> = &queue;
/// ``` /// ```
#[inline] #[inline]
pub fn as_view(&self) -> &MpMcQueueView<T> { pub fn as_view(&self) -> &QueueView<T> {
S::as_mpmc_view(self) S::as_mpmc_view(self)
} }
/// Get a mutable reference to the `MpMcQueue`, erasing the `N` const-generic. /// Get a mutable reference to the `Queue`, erasing the `N` const-generic.
/// ///
/// ```rust /// ```rust
/// # use heapless::mpmc::{MpMcQueue, MpMcQueueView}; /// # use heapless::mpmc::{Queue, QueueView};
/// let mut queue: MpMcQueue<u8, 2> = MpMcQueue::new(); /// let mut queue: Queue<u8, 2> = Queue::new();
/// let view: &mut MpMcQueueView<u8> = queue.as_mut_view(); /// let view: &mut QueueView<u8> = queue.as_mut_view();
/// ``` /// ```
/// ///
/// It is often preferable to do the same through type coerction, since `MpMcQueue<T, N>` implements `Unsize<MpMcQueueView<T>>`: /// It is often preferable to do the same through type coerction, since `Queue<T, N>` implements `Unsize<QueueView<T>>`:
/// ///
/// ```rust /// ```rust
/// # use heapless::mpmc::{MpMcQueue, MpMcQueueView}; /// # use heapless::mpmc::{Queue, QueueView};
/// let mut queue: MpMcQueue<u8, 2> = MpMcQueue::new(); /// let mut queue: Queue<u8, 2> = Queue::new();
/// let view: &mut MpMcQueueView<u8> = &mut queue; /// let view: &mut QueueView<u8> = &mut queue;
/// ``` /// ```
#[inline] #[inline]
pub fn as_mut_view(&mut self) -> &mut MpMcQueueView<T> { pub fn as_mut_view(&mut self) -> &mut QueueView<T> {
S::as_mpmc_mut_view(self) S::as_mpmc_mut_view(self)
} }
@ -250,20 +232,20 @@ impl<T, S: Storage> MpMcQueueInner<T, S> {
} }
} }
impl<T, const N: usize> Default for MpMcQueue<T, N> { impl<T, const N: usize> Default for Queue<T, N> {
fn default() -> Self { fn default() -> Self {
Self::new() Self::new()
} }
} }
impl<T, S: Storage> Drop for MpMcQueueInner<T, S> { impl<T, S: Storage> Drop for QueueInner<T, S> {
fn drop(&mut self) { fn drop(&mut self) {
// drop all contents currently in the queue // drop all contents currently in the queue
while self.dequeue().is_some() {} while self.dequeue().is_some() {}
} }
} }
unsafe impl<T, S: Storage> Sync for MpMcQueueInner<T, S> where T: Send {} unsafe impl<T, S: Storage> Sync for QueueInner<T, S> where T: Send {}
struct Cell<T> { struct Cell<T> {
data: MaybeUninit<T>, data: MaybeUninit<T>,
@ -370,16 +352,16 @@ unsafe fn enqueue<T>(
mod tests { mod tests {
use static_assertions::assert_not_impl_any; use static_assertions::assert_not_impl_any;
use super::{MpMcQueue, Q2}; use super::Queue;
// Ensure a `MpMcQueue` containing `!Send` values stays `!Send` itself. // Ensure a `Queue` containing `!Send` values stays `!Send` itself.
assert_not_impl_any!(MpMcQueue<*const (), 4>: Send); assert_not_impl_any!(Queue<*const (), 4>: Send);
#[test] #[test]
fn memory_leak() { fn memory_leak() {
droppable!(); droppable!();
let q = Q2::new(); let q = Queue::<_, 2>::new();
q.enqueue(Droppable::new()).unwrap_or_else(|_| panic!()); q.enqueue(Droppable::new()).unwrap_or_else(|_| panic!());
q.enqueue(Droppable::new()).unwrap_or_else(|_| panic!()); q.enqueue(Droppable::new()).unwrap_or_else(|_| panic!());
drop(q); drop(q);
@ -389,7 +371,7 @@ mod tests {
#[test] #[test]
fn sanity() { fn sanity() {
let q = Q2::new(); let q = Queue::<_, 2>::new();
q.enqueue(0).unwrap(); q.enqueue(0).unwrap();
q.enqueue(1).unwrap(); q.enqueue(1).unwrap();
assert!(q.enqueue(2).is_err()); assert!(q.enqueue(2).is_err());
@ -401,7 +383,7 @@ mod tests {
#[test] #[test]
fn drain_at_pos255() { fn drain_at_pos255() {
let q = Q2::new(); let q = Queue::<_, 2>::new();
for _ in 0..255 { for _ in 0..255 {
assert!(q.enqueue(0).is_ok()); assert!(q.enqueue(0).is_ok());
assert_eq!(q.dequeue(), Some(0)); assert_eq!(q.dequeue(), Some(0));
@ -413,7 +395,7 @@ mod tests {
#[test] #[test]
fn full_at_wrapped_pos0() { fn full_at_wrapped_pos0() {
let q = Q2::new(); let q = Queue::<_, 2>::new();
for _ in 0..254 { for _ in 0..254 {
assert!(q.enqueue(0).is_ok()); assert!(q.enqueue(0).is_ok());
assert_eq!(q.dequeue(), Some(0)); assert_eq!(q.dequeue(), Some(0));
@ -432,7 +414,7 @@ mod tests {
#[cfg(feature = "mpmc_large")] #[cfg(feature = "mpmc_large")]
const CAPACITY: usize = 256; const CAPACITY: usize = 256;
let q: MpMcQueue<u8, CAPACITY> = MpMcQueue::new(); let q: Queue<u8, CAPACITY> = Queue::new();
for _ in 0..CAPACITY { for _ in 0..CAPACITY {
q.enqueue(0xAA).unwrap(); q.enqueue(0xAA).unwrap();

View File

@ -14,7 +14,7 @@ use crate::spsc;
all(feature = "mpmc_large", target_has_atomic = "ptr"), all(feature = "mpmc_large", target_has_atomic = "ptr"),
all(not(feature = "mpmc_large"), target_has_atomic = "8") all(not(feature = "mpmc_large"), target_has_atomic = "8")
))] ))]
use crate::mpmc::{MpMcQueue, MpMcQueueInner, MpMcQueueView}; use crate::mpmc;
pub(crate) trait SealedStorage { pub(crate) trait SealedStorage {
type Buffer<T>: ?Sized + Borrow<[T]> + BorrowMut<[T]>; type Buffer<T>: ?Sized + Borrow<[T]> + BorrowMut<[T]>;
@ -30,7 +30,7 @@ pub(crate) trait SealedStorage {
all(feature = "mpmc_large", target_has_atomic = "ptr"), all(feature = "mpmc_large", target_has_atomic = "ptr"),
all(not(feature = "mpmc_large"), target_has_atomic = "8") all(not(feature = "mpmc_large"), target_has_atomic = "8")
))] ))]
fn as_mpmc_view<T>(this: &MpMcQueueInner<T, Self>) -> &MpMcQueueView<T> fn as_mpmc_view<T>(this: &mpmc::QueueInner<T, Self>) -> &mpmc::QueueView<T>
where where
Self: Storage + Sized; Self: Storage + Sized;
#[cfg(any( #[cfg(any(
@ -38,7 +38,7 @@ pub(crate) trait SealedStorage {
all(feature = "mpmc_large", target_has_atomic = "ptr"), all(feature = "mpmc_large", target_has_atomic = "ptr"),
all(not(feature = "mpmc_large"), target_has_atomic = "8") all(not(feature = "mpmc_large"), target_has_atomic = "8")
))] ))]
fn as_mpmc_mut_view<T>(this: &mut MpMcQueueInner<T, Self>) -> &mut MpMcQueueView<T> fn as_mpmc_mut_view<T>(this: &mut mpmc::QueueInner<T, Self>) -> &mut mpmc::QueueView<T>
where where
Self: Storage + Sized; Self: Storage + Sized;
@ -100,7 +100,7 @@ impl<const N: usize> SealedStorage for OwnedStorage<N> {
all(feature = "mpmc_large", target_has_atomic = "ptr"), all(feature = "mpmc_large", target_has_atomic = "ptr"),
all(not(feature = "mpmc_large"), target_has_atomic = "8") all(not(feature = "mpmc_large"), target_has_atomic = "8")
))] ))]
fn as_mpmc_view<T>(this: &MpMcQueue<T, N>) -> &MpMcQueueView<T> fn as_mpmc_view<T>(this: &mpmc::Queue<T, N>) -> &mpmc::QueueView<T>
where where
Self: Storage + Sized, Self: Storage + Sized,
{ {
@ -112,7 +112,7 @@ impl<const N: usize> SealedStorage for OwnedStorage<N> {
all(feature = "mpmc_large", target_has_atomic = "ptr"), all(feature = "mpmc_large", target_has_atomic = "ptr"),
all(not(feature = "mpmc_large"), target_has_atomic = "8") all(not(feature = "mpmc_large"), target_has_atomic = "8")
))] ))]
fn as_mpmc_mut_view<T>(this: &mut MpMcQueue<T, N>) -> &mut MpMcQueueView<T> fn as_mpmc_mut_view<T>(this: &mut mpmc::Queue<T, N>) -> &mut mpmc::QueueView<T>
where where
Self: Storage + Sized, Self: Storage + Sized,
{ {
@ -165,7 +165,7 @@ impl SealedStorage for ViewStorage {
all(feature = "mpmc_large", target_has_atomic = "ptr"), all(feature = "mpmc_large", target_has_atomic = "ptr"),
all(not(feature = "mpmc_large"), target_has_atomic = "8") all(not(feature = "mpmc_large"), target_has_atomic = "8")
))] ))]
fn as_mpmc_view<T>(this: &MpMcQueueInner<T, Self>) -> &MpMcQueueView<T> fn as_mpmc_view<T>(this: &mpmc::QueueInner<T, Self>) -> &mpmc::QueueView<T>
where where
Self: Storage + Sized, Self: Storage + Sized,
{ {
@ -177,7 +177,7 @@ impl SealedStorage for ViewStorage {
all(feature = "mpmc_large", target_has_atomic = "ptr"), all(feature = "mpmc_large", target_has_atomic = "ptr"),
all(not(feature = "mpmc_large"), target_has_atomic = "8") all(not(feature = "mpmc_large"), target_has_atomic = "8")
))] ))]
fn as_mpmc_mut_view<T>(this: &mut MpMcQueueInner<T, Self>) -> &mut MpMcQueueView<T> fn as_mpmc_mut_view<T>(this: &mut mpmc::QueueInner<T, Self>) -> &mut mpmc::QueueView<T>
where where
Self: Storage + Sized, Self: Storage + Sized,
{ {

View File

@ -119,11 +119,11 @@ fn contention() {
fn mpmc_contention() { fn mpmc_contention() {
use std::sync::mpsc; use std::sync::mpsc;
use heapless::mpmc::Q64; use heapless::mpmc::Queue;
const N: u32 = 64; const N: u32 = 64;
static Q: Q64<u32> = Q64::new(); static Q: Queue<u32, 64> = Queue::new();
let (s, r) = mpsc::channel(); let (s, r) = mpsc::channel();
thread::scope(|scope| { thread::scope(|scope| {