51
51
//! // scope.
52
52
//! let queue: &'static mut Queue<Event, 4> = {
53
53
//! static mut Q: Queue<Event, 4> = Queue::new();
54
+ //! // SAFETY: `Q` is only accessible in this scope
55
+ /// // and `main` is only called once.
54
56
//! unsafe { &mut Q }
55
57
//! };
56
58
//!
@@ -128,16 +130,21 @@ pub struct QueueInner<T, S: Storage> {
128
130
pub ( crate ) buffer : S :: Buffer < UnsafeCell < MaybeUninit < T > > > ,
129
131
}
130
132
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.
132
134
///
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.
135
143
pub type Queue < T , const N : usize > = QueueInner < T , OwnedStorage < N > > ;
136
144
137
- /// Asingle producer single consumer queue
145
+ /// A [`Queue`] with dynamic capacity.
138
146
///
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.
141
148
pub type QueueView < T > = QueueInner < T , ViewStorage > ;
142
149
143
150
impl < T , const N : usize > Queue < T , N > {
@@ -352,8 +359,108 @@ impl<T, S: Storage> QueueInner<T, S> {
352
359
self . inner_dequeue_unchecked ( )
353
360
}
354
361
355
- /// Splits a queue into producer and consumer endpoints
356
- pub fn split ( & mut self ) -> ( ProducerInner < ' _ , T , S > , ConsumerInner < ' _ , T , S > ) {
362
+ /// Splits a queue into producer and consumer endpoints.
363
+ ///
364
+ /// # Examples
365
+ ///
366
+ /// Create a queue at compile time, split it at runtime,
367
+ /// and pass it to an interrupt handler via a mutex.
368
+ ///
369
+ /// ```
370
+ /// use core::cell::RefCell;
371
+ /// use critical_section::Mutex;
372
+ /// use heapless::spsc::{Producer, Queue};
373
+ ///
374
+ /// static PRODUCER: Mutex<RefCell<Option<Producer<'static, (), 4>>>> =
375
+ /// Mutex::new(RefCell::new(None));
376
+ ///
377
+ /// fn interrupt() {
378
+ /// let mut producer = {
379
+ /// static mut P: Option<Producer<'static, (), 4>> = None;
380
+ /// // SAFETY: Mutable access to `P` is allowed exclusively in this scope
381
+ /// // and `interrupt` cannot be called directly or preempt itself.
382
+ /// unsafe { &mut P }
383
+ /// }
384
+ /// .get_or_insert_with(|| {
385
+ /// critical_section::with(|cs| PRODUCER.borrow_ref_mut(cs).take().unwrap())
386
+ /// });
387
+ ///
388
+ /// producer.enqueue(()).unwrap();
389
+ /// }
390
+ ///
391
+ /// fn main() {
392
+ /// let mut consumer = {
393
+ /// let (p, c) = {
394
+ /// static mut Q: Queue<(), 4> = Queue::new();
395
+ /// // SAFETY: `Q` is only accessible in this scope
396
+ /// // and `main` is only called once.
397
+ /// #[allow(static_mut_refs)]
398
+ /// unsafe { Q.split() }
399
+ /// };
400
+ ///
401
+ /// critical_section::with(move |cs| {
402
+ /// let mut producer = PRODUCER.borrow_ref_mut(cs);
403
+ /// *producer = Some(p);
404
+ /// });
405
+ ///
406
+ /// c
407
+ /// };
408
+ ///
409
+ /// // Interrupt occurs.
410
+ /// # interrupt();
411
+ ///
412
+ /// consumer.dequeue().unwrap();
413
+ /// }
414
+ /// ```
415
+ ///
416
+ /// Create and split a queue at compile time, and pass it to the main
417
+ /// function and an interrupt handler via a mutex at runtime.
418
+ ///
419
+ /// ```
420
+ /// use core::cell::RefCell;
421
+ ///
422
+ /// use critical_section::Mutex;
423
+ /// use heapless::spsc::{Consumer, Producer, Queue};
424
+ ///
425
+ /// static PC: (
426
+ /// Mutex<RefCell<Option<Producer<'_, (), 4>>>>,
427
+ /// Mutex<RefCell<Option<Consumer<'_, (), 4>>>>,
428
+ /// ) = {
429
+ /// static mut Q: Queue<(), 4> = Queue::new();
430
+ /// // SAFETY: `Q` is only accessible in this scope.
431
+ /// #[allow(static_mut_refs)]
432
+ /// let (p, c) = unsafe { Q.split() };
433
+ ///
434
+ /// (
435
+ /// Mutex::new(RefCell::new(Some(p))),
436
+ /// Mutex::new(RefCell::new(Some(c))),
437
+ /// )
438
+ /// };
439
+ ///
440
+ /// fn interrupt() {
441
+ /// let mut producer = {
442
+ /// static mut P: Option<Producer<'_, (), 4>> = None;
443
+ /// // SAFETY: Mutable access to `P` is allowed exclusively in this scope
444
+ /// // and `interrupt` cannot be called directly or preempt itself.
445
+ /// unsafe { &mut P }
446
+ /// }
447
+ /// .get_or_insert_with(|| {
448
+ /// critical_section::with(|cs| PC.0.borrow_ref_mut(cs).take().unwrap())
449
+ /// });
450
+ ///
451
+ /// producer.enqueue(()).unwrap();
452
+ /// }
453
+ ///
454
+ /// fn main() {
455
+ /// let mut consumer = critical_section::with(|cs| PC.1.borrow_ref_mut(cs).take().unwrap());
456
+ ///
457
+ /// // Interrupt occurs.
458
+ /// # interrupt();
459
+ ///
460
+ /// consumer.dequeue().unwrap();
461
+ /// }
462
+ /// ```
463
+ pub const fn split ( & mut self ) -> ( ProducerInner < ' _ , T , S > , ConsumerInner < ' _ , T , S > ) {
357
464
( ProducerInner { rb : self } , ConsumerInner { rb : self } )
358
465
}
359
466
}
@@ -372,9 +479,9 @@ where
372
479
let mut new: Self = Self :: new ( ) ;
373
480
374
481
for s in self . iter ( ) {
482
+ // SAFETY: `new.capacity() == self.capacity() >= self.len()`,
483
+ // so no overflow is possible.
375
484
unsafe {
376
- // NOTE(unsafe) new.capacity() == self.capacity() >= self.len()
377
- // no overflow possible
378
485
new. enqueue_unchecked ( s. clone ( ) ) ;
379
486
}
380
487
}
@@ -734,6 +841,38 @@ mod tests {
734
841
// Ensure a `Consumer` containing `!Send` values stays `!Send` itself.
735
842
assert_not_impl_any ! ( Consumer <* const ( ) , 4 >: Send ) ;
736
843
844
+ #[ test]
845
+ fn const_split ( ) {
846
+ use critical_section:: Mutex ;
847
+ use std:: cell:: RefCell ;
848
+
849
+ use super :: { Consumer , Producer } ;
850
+
851
+ #[ allow( clippy:: type_complexity) ]
852
+ static PC : (
853
+ Mutex < RefCell < Option < Producer < ' _ , ( ) , 4 > > > > ,
854
+ Mutex < RefCell < Option < Consumer < ' _ , ( ) , 4 > > > > ,
855
+ ) = {
856
+ static mut Q : Queue < ( ) , 4 > = Queue :: new ( ) ;
857
+ // SAFETY: `Q` is only accessible in this scope.
858
+ #[ allow( static_mut_refs) ]
859
+ let ( p, c) = unsafe { Q . split ( ) } ;
860
+
861
+ (
862
+ Mutex :: new ( RefCell :: new ( Some ( p) ) ) ,
863
+ Mutex :: new ( RefCell :: new ( Some ( c) ) ) ,
864
+ )
865
+ } ;
866
+ let producer = critical_section:: with ( |cs| PC . 0 . borrow_ref_mut ( cs) . take ( ) . unwrap ( ) ) ;
867
+ let consumer = critical_section:: with ( |cs| PC . 1 . borrow_ref_mut ( cs) . take ( ) . unwrap ( ) ) ;
868
+
869
+ let mut producer: Producer < ' static , ( ) , 4 > = producer;
870
+ let mut consumer: Consumer < ' static , ( ) , 4 > = consumer;
871
+
872
+ assert_eq ! ( producer. enqueue( ( ) ) , Ok ( ( ) ) ) ;
873
+ assert_eq ! ( consumer. dequeue( ) , Some ( ( ) ) ) ;
874
+ }
875
+
737
876
#[ test]
738
877
fn full ( ) {
739
878
let mut rb: Queue < i32 , 3 > = Queue :: new ( ) ;
0 commit comments