@@ -128,16 +128,21 @@ pub struct QueueInner<T, S: Storage> {
128
128
pub ( crate ) buffer : S :: Buffer < UnsafeCell < MaybeUninit < T > > > ,
129
129
}
130
130
131
- /// A statically allocated single producer single consumer queue with a capacity of `N - 1` elements
131
+ /// A statically allocated single producer, single consumer queue with a capacity of `N - 1` elements.
132
132
///
133
- /// *IMPORTANT*: To get better performance use a value for `N` that is a power of 2 (e.g. `16`, `32`,
134
- /// etc.).
133
+ /// >
134
+ /// <div class="warning">
135
+ ///
136
+ /// To get better performance use a value for `N` that is a power of 2, e.g. 16, 32, etc.
137
+ ///
138
+ /// </div>
139
+ ///
140
+ /// You will likely want to use [`split`](QueueInner::split) to create a producer and consumer handle.
135
141
pub type Queue < T , const N : usize > = QueueInner < T , OwnedStorage < N > > ;
136
142
137
- /// Asingle producer single consumer queue
143
+ /// A [`Queue`] with dynamic capacity.
138
144
///
139
- /// *IMPORTANT*: To get better performance use a value for `N` that is a power of 2 (e.g. `16`, `32`,
140
- /// etc.).
145
+ /// [`Queue`] coerces to `QueueView`. `QueueView` is `!Sized`, meaning it can only ever be used by reference.
141
146
pub type QueueView < T > = QueueInner < T , ViewStorage > ;
142
147
143
148
impl < T , const N : usize > Queue < T , N > {
@@ -352,8 +357,106 @@ impl<T, S: Storage> QueueInner<T, S> {
352
357
self . inner_dequeue_unchecked ( )
353
358
}
354
359
355
- /// Splits a queue into producer and consumer endpoints
356
- pub fn split ( & mut self ) -> ( ProducerInner < ' _ , T , S > , ConsumerInner < ' _ , T , S > ) {
360
+ /// Splits a queue into producer and consumer endpoints.
361
+ ///
362
+ /// # Examples
363
+ ///
364
+ /// Create a queue at compile time, split it at runtime,
365
+ /// and pass it to an interrupt handler via a mutex.
366
+ ///
367
+ /// ```
368
+ /// use core::cell::RefCell;
369
+ /// use critical_section::Mutex;
370
+ /// use heapless::spsc::{Producer, Queue};
371
+ ///
372
+ /// static PRODUCER: Mutex<RefCell<Option<Producer<'static, (), 4>>>> =
373
+ /// Mutex::new(RefCell::new(None));
374
+ ///
375
+ /// fn interrupt() {
376
+ /// let mut producer = {
377
+ /// static mut P: Option<Producer<'static, (), 4>> = None;
378
+ /// // SAFETY: Mutable access to `P` is allowed exclusively in this scope
379
+ /// // and `interrupt` cannot be called directly or preempt itself.
380
+ /// unsafe { &mut P }
381
+ /// }
382
+ /// .get_or_insert_with(|| {
383
+ /// critical_section::with(|cs| PRODUCER.borrow_ref_mut(cs).take().unwrap())
384
+ /// });
385
+ ///
386
+ /// producer.enqueue(()).unwrap();
387
+ /// }
388
+ ///
389
+ /// fn main() {
390
+ /// let mut consumer = {
391
+ /// let (p, c) = {
392
+ /// static mut Q: Queue<(), 4> = Queue::new();
393
+ /// // SAFETY: `Q` is accessed mutably exclusively in this scope
394
+ /// // and `main` is only called once.
395
+ /// unsafe { Q.split() }
396
+ /// };
397
+ ///
398
+ /// critical_section::with(move |cs| {
399
+ /// let mut producer = PRODUCER.borrow_ref_mut(cs);
400
+ /// *producer = Some(p);
401
+ /// });
402
+ ///
403
+ /// c
404
+ /// };
405
+ ///
406
+ /// // Interrupt occurs.
407
+ /// # interrupt();
408
+ ///
409
+ /// consumer.dequeue().unwrap();
410
+ /// }
411
+ /// ```
412
+ ///
413
+ /// Create and split a queue at compile time, and pass it to the main
414
+ /// function and an interrupt handler via a mutex at runtime.
415
+ ///
416
+ /// ```
417
+ /// use core::cell::RefCell;
418
+ ///
419
+ /// use critical_section::Mutex;
420
+ /// use heapless::spsc::{Consumer, Producer, Queue};
421
+ ///
422
+ /// static PC: (
423
+ /// Mutex<RefCell<Option<Producer<'_, (), 4>>>>,
424
+ /// Mutex<RefCell<Option<Consumer<'_, (), 4>>>>,
425
+ /// ) = {
426
+ /// static mut Q: Queue<(), 4> = Queue::new();
427
+ /// // SAFETY: `Q` is accessed mutably exclusively in this scope.
428
+ /// let (p, c) = unsafe { Q.split() };
429
+ ///
430
+ /// (
431
+ /// Mutex::new(RefCell::new(Some(p))),
432
+ /// Mutex::new(RefCell::new(Some(c))),
433
+ /// )
434
+ /// };
435
+ ///
436
+ /// fn interrupt() {
437
+ /// let mut producer = {
438
+ /// static mut P: Option<Producer<'_, (), 4>> = None;
439
+ /// // SAFETY: Mutable access to `P` is allowed exclusively in this scope
440
+ /// // and `interrupt` cannot be called directly or preempt itself.
441
+ /// unsafe { &mut P }
442
+ /// }
443
+ /// .get_or_insert_with(|| {
444
+ /// critical_section::with(|cs| PC.0.borrow_ref_mut(cs).take().unwrap())
445
+ /// });
446
+ ///
447
+ /// producer.enqueue(()).unwrap();
448
+ /// }
449
+ ///
450
+ /// fn main() {
451
+ /// let mut consumer = critical_section::with(|cs| PC.1.borrow_ref_mut(cs).take().unwrap());
452
+ ///
453
+ /// // Interrupt occurs.
454
+ /// # interrupt();
455
+ ///
456
+ /// consumer.dequeue().unwrap();
457
+ /// }
458
+ /// ```
459
+ pub const fn split ( & mut self ) -> ( ProducerInner < ' _ , T , S > , ConsumerInner < ' _ , T , S > ) {
357
460
( ProducerInner { rb : self } , ConsumerInner { rb : self } )
358
461
}
359
462
}
@@ -734,6 +837,36 @@ mod tests {
734
837
// Ensure a `Consumer` containing `!Send` values stays `!Send` itself.
735
838
assert_not_impl_any ! ( Consumer <* const ( ) , 4 >: Send ) ;
736
839
840
+ #[ cfg( feature = "nightly" ) ]
841
+ #[ test]
842
+ fn const_split ( ) {
843
+ use critical_section:: Mutex ;
844
+ use std:: cell:: RefCell ;
845
+
846
+ use super :: { Consumer , Producer } ;
847
+
848
+ static PC : (
849
+ Mutex < RefCell < Option < Producer < ' _ , ( ) , 4 > > > > ,
850
+ Mutex < RefCell < Option < Consumer < ' _ , ( ) , 4 > > > > ,
851
+ ) = {
852
+ static mut Q : Queue < ( ) , 4 > = Queue :: new ( ) ;
853
+ let ( p, c) = unsafe { Q . split ( ) } ;
854
+
855
+ (
856
+ Mutex :: new ( RefCell :: new ( Some ( p) ) ) ,
857
+ Mutex :: new ( RefCell :: new ( Some ( c) ) ) ,
858
+ )
859
+ } ;
860
+ let producer = critical_section:: with ( |cs| PC . 0 . borrow_ref_mut ( cs) . take ( ) . unwrap ( ) ) ;
861
+ let consumer = critical_section:: with ( |cs| PC . 1 . borrow_ref_mut ( cs) . take ( ) . unwrap ( ) ) ;
862
+
863
+ let mut producer: Producer < ' static , ( ) , 4 > = producer;
864
+ let mut consumer: Consumer < ' static , ( ) , 4 > = consumer;
865
+
866
+ assert_eq ! ( producer. enqueue( ( ) ) , Ok ( ( ) ) ) ;
867
+ assert_eq ! ( consumer. dequeue( ) , Some ( ( ) ) ) ;
868
+ }
869
+
737
870
#[ test]
738
871
fn full ( ) {
739
872
let mut rb: Queue < i32 , 3 > = Queue :: new ( ) ;
0 commit comments