11//! A fixed capacity multiple-producer, multiple-consumer (MPMC) lock-free queue.
22//!
3+ //! # Deprecation
4+ //!
5+ //! <div class="warning">
6+ //! The current implementation of `mpmc` is marked as deprecated due to not being truly lock-free
7+ //! </div>
8+ //!
9+ //! If a thread is parked, or pre-empted for a long time by an higher-priority task
10+ //! during an `enqueue` or `dequeue` operation, it is possible that the queue ends-up
11+ //! in a state were no other task can successfully enqueue or dequeue items from it
12+ //! until the pre-empted task can finish its operation.
13+ //!
14+ //! In that case, [`enqueue`](QueueInner::dequeue) and [`dequeue`](QueueInner::enqueue)
15+ //! will return an error, but will not panic or reach undefined behaviour
16+ //!
17+ //! This makes `mpmc` unsuitable for some use cases such as using it as a pool of objects.
18+ //!
19+ //! ## When can this queue be used?
20+ //!
21+ //! This queue should be used for cross-task communication only when items sent over the queue
22+ //! can be dropped in case of concurrent operations, or when it is possible to retry
23+ //! the dequeue/enqueue operation after other tasks have had the opportunity to make progress.
24+ //!
25+ //! In that case you can safely ignore the warnings using `#[expect(deprecated)]`
26+ //! when `new` is called
27+ //!
28+ //! For more information, and possible alternative, please see
29+ //! <https://github.com/rust-embedded/heapless/issues/583>
30+ //!
31+ //!
332//! **Note:** This module requires atomic compare-and-swap (CAS) instructions. On
433//! targets where they're not natively available, they are emulated by the
534//! [`portable-atomic`](https://crates.io/crates/portable-atomic) crate.
@@ -121,7 +150,38 @@ pub type Queue<T, const N: usize> = QueueInner<T, OwnedStorage<N>>;
121150pub type QueueView < T > = QueueInner < T , ViewStorage > ;
122151
123152impl < T , const N : usize > Queue < T , N > {
153+ #[ deprecated(
154+ note = "See the documentation of Queue::new() for more information: https://docs.rs/heapless/latest/heapless/mpmc/type.Queue.html#method.new"
155+ ) ]
124156 /// Creates an empty queue.
157+ ///
158+ /// # Deprecation
159+ ///
160+ /// <div class="warning">
161+ /// The current implementation of `mpmc` is marked as deprecated due to not being truly lock-free
162+ /// </div>
163+ ///
164+ /// If a thread is parked, or pre-empted for a long time by an higher-priority task
165+ /// during an `enqueue` or `dequeue` operation, it is possible that the queue ends-up
166+ /// in a state were no other task can successfully enqueue or dequeue items from it
167+ /// until the pre-empted task can finish its operation.
168+ ///
169+ /// In that case, [`enqueue`](QueueInner::dequeue) and [`dequeue`](QueueInner::enqueue)
170+ /// will return an error, but will not panic or reach undefined behaviour
171+ ///
172+ /// This makes `mpmc` unsuitable for some use cases such as using it as a pool of objects.
173+ ///
174+ /// ## When can this queue be used?
175+ ///
176+ /// This queue should be used for cross-task communication only when items sent over the queue
177+ /// can be dropped in case of concurrent operations, or when it is possible to retry
178+ /// the dequeue/enqueue operation after other tasks have had the opportunity to make progress.
179+ ///
180+ /// In that case you can safely ignore the warnings using `#[expect(deprecated)]`
181+ /// when `new` is called
182+ ///
183+ /// For more information, and possible alternative, please see
184+ /// <https://github.com/rust-embedded/heapless/issues/583>
125185 pub const fn new ( ) -> Self {
126186 const {
127187 assert ! ( N > 1 ) ;
@@ -186,6 +246,7 @@ impl<T, S: Storage> QueueInner<T, S> {
186246 ///
187247 /// ```rust
188248 /// # use heapless::mpmc::{Queue, QueueView};
249+ /// ##[expect(deprecated)]
189250 /// let mut queue: Queue<u8, 2> = Queue::new();
190251 /// let view: &mut QueueView<u8> = queue.as_mut_view();
191252 /// ```
@@ -194,6 +255,7 @@ impl<T, S: Storage> QueueInner<T, S> {
194255 ///
195256 /// ```rust
196257 /// # use heapless::mpmc::{Queue, QueueView};
258+ /// ##[expect(deprecated)]
197259 /// let mut queue: Queue<u8, 2> = Queue::new();
198260 /// let view: &mut QueueView<u8> = &mut queue;
199261 /// ```
@@ -228,6 +290,7 @@ impl<T, S: Storage> QueueInner<T, S> {
228290
229291impl < T , const N : usize > Default for Queue < T , N > {
230292 fn default ( ) -> Self {
293+ #[ allow( deprecated) ]
231294 Self :: new ( )
232295 }
233296}
@@ -355,6 +418,7 @@ mod tests {
355418 fn memory_leak ( ) {
356419 droppable ! ( ) ;
357420
421+ #[ expect( deprecated) ]
358422 let q = Queue :: < _ , 2 > :: new ( ) ;
359423 q. enqueue ( Droppable :: new ( ) ) . unwrap_or_else ( |_| panic ! ( ) ) ;
360424 q. enqueue ( Droppable :: new ( ) ) . unwrap_or_else ( |_| panic ! ( ) ) ;
@@ -365,6 +429,7 @@ mod tests {
365429
366430 #[ test]
367431 fn sanity ( ) {
432+ #[ expect( deprecated) ]
368433 let q = Queue :: < _ , 2 > :: new ( ) ;
369434 q. enqueue ( 0 ) . unwrap ( ) ;
370435 q. enqueue ( 1 ) . unwrap ( ) ;
@@ -377,6 +442,7 @@ mod tests {
377442
378443 #[ test]
379444 fn drain_at_pos255 ( ) {
445+ #[ expect( deprecated) ]
380446 let q = Queue :: < _ , 2 > :: new ( ) ;
381447 for _ in 0 ..255 {
382448 assert ! ( q. enqueue( 0 ) . is_ok( ) ) ;
@@ -389,6 +455,7 @@ mod tests {
389455
390456 #[ test]
391457 fn full_at_wrapped_pos0 ( ) {
458+ #[ expect( deprecated) ]
392459 let q = Queue :: < _ , 2 > :: new ( ) ;
393460 for _ in 0 ..254 {
394461 assert ! ( q. enqueue( 0 ) . is_ok( ) ) ;
@@ -408,6 +475,7 @@ mod tests {
408475 #[ cfg( feature = "mpmc_large" ) ]
409476 const CAPACITY : usize = 256 ;
410477
478+ #[ expect( deprecated) ]
411479 let q: Queue < u8 , CAPACITY > = Queue :: new ( ) ;
412480
413481 assert_eq ! ( q. capacity( ) , CAPACITY ) ;
0 commit comments