5151//! // scope.
5252//! let queue: &'static mut Queue<Event, 4> = {
5353//! static mut Q: Queue<Event, 4> = Queue::new();
54+ //! // SAFETY: `Q` is only accessible in this scope
55+ //! // and `main` is only called once.
5456//! unsafe { &mut Q }
5557//! };
5658//!
@@ -128,16 +130,21 @@ pub struct QueueInner<T, S: Storage> {
128130 pub ( crate ) buffer : S :: Buffer < UnsafeCell < MaybeUninit < T > > > ,
129131}
130132
131- /// A statically allocated single producer single consumer queue with a capacity of `N - 1` elements
133+ /// A statically allocated single producer, single consumer queue with a capacity of `N - 1` elements.
132134///
133- /// *IMPORTANT*: To get better performance use a value for `N` that is a power of 2 (e.g. `16`, `32`,
134- /// etc.).
135+ /// >
136+ /// <div class="warning">
137+ ///
138+ /// To get better performance use a value for `N` that is a power of 2, e.g. 16, 32, etc.
139+ ///
140+ /// </div>
141+ ///
142+ /// You will likely want to use [`split`](QueueInner::split) to create a producer and consumer handle.
135143pub type Queue < T , const N : usize > = QueueInner < T , OwnedStorage < N > > ;
136144
137- /// Asingle producer single consumer queue
145+ /// A [`Queue`] with dynamic capacity.
138146///
139- /// *IMPORTANT*: To get better performance use a value for `N` that is a power of 2 (e.g. `16`, `32`,
140- /// etc.).
147+ /// [`Queue`] coerces to `QueueView`. `QueueView` is `!Sized`, meaning it can only ever be used by reference.
141148pub type QueueView < T > = QueueInner < T , ViewStorage > ;
142149
143150impl < T , const N : usize > Queue < T , N > {
@@ -362,8 +369,110 @@ impl<T, S: Storage> QueueInner<T, S> {
362369 self . inner_dequeue_unchecked ( )
363370 }
364371
365- /// Splits a queue into producer and consumer endpoints
366- pub fn split ( & mut self ) -> ( ProducerInner < ' _ , T , S > , ConsumerInner < ' _ , T , S > ) {
372+ /// Splits a queue into producer and consumer endpoints.
373+ ///
374+ /// # Examples
375+ ///
376+ /// Create a queue at compile time, split it at runtime,
377+ /// and pass it to an interrupt handler via a mutex.
378+ ///
379+ /// ```
380+ /// use core::cell::RefCell;
381+ /// use critical_section::Mutex;
382+ /// use heapless::spsc::{Producer, Queue};
383+ ///
384+ /// static PRODUCER: Mutex<RefCell<Option<Producer<'static, (), 4>>>> =
385+ /// Mutex::new(RefCell::new(None));
386+ ///
387+ /// fn interrupt() {
388+ /// let mut producer = {
389+ /// static mut P: Option<Producer<'static, (), 4>> = None;
390+ /// // SAFETY: Mutable access to `P` is allowed exclusively in this scope
391+ /// // and `interrupt` cannot be called directly or preempt itself.
392+ /// unsafe { &mut P }
393+ /// }
394+ /// .get_or_insert_with(|| {
395+ /// critical_section::with(|cs| PRODUCER.borrow_ref_mut(cs).take().unwrap())
396+ /// });
397+ ///
398+ /// producer.enqueue(()).unwrap();
399+ /// }
400+ ///
401+ /// fn main() {
402+ /// let mut consumer = {
403+ /// let (p, c) = {
404+ /// static mut Q: Queue<(), 4> = Queue::new();
405+ /// // SAFETY: `Q` is only accessible in this scope
406+ /// // and `main` is only called once.
407+ /// #[allow(static_mut_refs)]
408+ /// unsafe {
409+ /// Q.split()
410+ /// }
411+ /// };
412+ ///
413+ /// critical_section::with(move |cs| {
414+ /// let mut producer = PRODUCER.borrow_ref_mut(cs);
415+ /// *producer = Some(p);
416+ /// });
417+ ///
418+ /// c
419+ /// };
420+ ///
421+ /// // Interrupt occurs.
422+ /// # interrupt();
423+ ///
424+ /// consumer.dequeue().unwrap();
425+ /// }
426+ /// ```
427+ ///
428+ /// Create and split a queue at compile time, and pass it to the main
429+ /// function and an interrupt handler via a mutex at runtime.
430+ ///
431+ /// ```
432+ /// use core::cell::RefCell;
433+ ///
434+ /// use critical_section::Mutex;
435+ /// use heapless::spsc::{Consumer, Producer, Queue};
436+ ///
437+ /// static PC: (
438+ /// Mutex<RefCell<Option<Producer<'_, (), 4>>>>,
439+ /// Mutex<RefCell<Option<Consumer<'_, (), 4>>>>,
440+ /// ) = {
441+ /// static mut Q: Queue<(), 4> = Queue::new();
442+ /// // SAFETY: `Q` is only accessible in this scope.
443+ /// #[allow(static_mut_refs)]
444+ /// let (p, c) = unsafe { Q.split() };
445+ ///
446+ /// (
447+ /// Mutex::new(RefCell::new(Some(p))),
448+ /// Mutex::new(RefCell::new(Some(c))),
449+ /// )
450+ /// };
451+ ///
452+ /// fn interrupt() {
453+ /// let mut producer = {
454+ /// static mut P: Option<Producer<'_, (), 4>> = None;
455+ /// // SAFETY: Mutable access to `P` is allowed exclusively in this scope
456+ /// // and `interrupt` cannot be called directly or preempt itself.
457+ /// unsafe { &mut P }
458+ /// }
459+ /// .get_or_insert_with(|| {
460+ /// critical_section::with(|cs| PC.0.borrow_ref_mut(cs).take().unwrap())
461+ /// });
462+ ///
463+ /// producer.enqueue(()).unwrap();
464+ /// }
465+ ///
466+ /// fn main() {
467+ /// let mut consumer = critical_section::with(|cs| PC.1.borrow_ref_mut(cs).take().unwrap());
468+ ///
469+ /// // Interrupt occurs.
470+ /// # interrupt();
471+ ///
472+ /// consumer.dequeue().unwrap();
473+ /// }
474+ /// ```
475+ pub const fn split ( & mut self ) -> ( ProducerInner < ' _ , T , S > , ConsumerInner < ' _ , T , S > ) {
367476 ( ProducerInner { rb : self } , ConsumerInner { rb : self } )
368477 }
369478}
@@ -382,9 +491,9 @@ where
382491 let mut new: Self = Self :: new ( ) ;
383492
384493 for s in self . iter ( ) {
494+ // SAFETY: `new.capacity() == self.capacity() >= self.len()`,
495+ // so no overflow is possible.
385496 unsafe {
386- // NOTE(unsafe) new.capacity() == self.capacity() >= self.len()
387- // no overflow possible
388497 new. enqueue_unchecked ( s. clone ( ) ) ;
389498 }
390499 }
@@ -744,6 +853,38 @@ mod tests {
744853 // Ensure a `Consumer` containing `!Send` values stays `!Send` itself.
745854 assert_not_impl_any ! ( Consumer <* const ( ) , 4 >: Send ) ;
746855
856+ #[ test]
857+ fn const_split ( ) {
858+ use critical_section:: Mutex ;
859+ use std:: cell:: RefCell ;
860+
861+ use super :: { Consumer , Producer } ;
862+
863+ #[ allow( clippy:: type_complexity) ]
864+ static PC : (
865+ Mutex < RefCell < Option < Producer < ' _ , ( ) , 4 > > > > ,
866+ Mutex < RefCell < Option < Consumer < ' _ , ( ) , 4 > > > > ,
867+ ) = {
868+ static mut Q : Queue < ( ) , 4 > = Queue :: new ( ) ;
869+ // SAFETY: `Q` is only accessible in this scope.
870+ #[ allow( static_mut_refs) ]
871+ let ( p, c) = unsafe { Q . split ( ) } ;
872+
873+ (
874+ Mutex :: new ( RefCell :: new ( Some ( p) ) ) ,
875+ Mutex :: new ( RefCell :: new ( Some ( c) ) ) ,
876+ )
877+ } ;
878+ let producer = critical_section:: with ( |cs| PC . 0 . borrow_ref_mut ( cs) . take ( ) . unwrap ( ) ) ;
879+ let consumer = critical_section:: with ( |cs| PC . 1 . borrow_ref_mut ( cs) . take ( ) . unwrap ( ) ) ;
880+
881+ let mut producer: Producer < ' static , ( ) , 4 > = producer;
882+ let mut consumer: Consumer < ' static , ( ) , 4 > = consumer;
883+
884+ assert_eq ! ( producer. enqueue( ( ) ) , Ok ( ( ) ) ) ;
885+ assert_eq ! ( consumer. dequeue( ) , Some ( ( ) ) ) ;
886+ }
887+
747888 #[ test]
748889 fn full ( ) {
749890 let mut rb: Queue < i32 , 3 > = Queue :: new ( ) ;
0 commit comments