@@ -305,10 +305,113 @@ impl<T, const N: usize> Queue<T, N> {
305
305
self . inner_dequeue_unchecked ( )
306
306
}
307
307
308
- /// Splits a queue into producer and consumer endpoints
308
+ /// Splits a queue into producer and consumer endpoints.
309
+ ///
310
+ /// # Examples
311
+ ///
312
+ /// ```
313
+ /// use core::cell::RefCell;
314
+ /// use critical_section::Mutex;
315
+ /// use heapless::spsc::{Producer, Queue};
316
+ ///
317
+ /// static PRODUCER: Mutex<RefCell<Option<Producer<'static, (), 4>>>> =
318
+ /// Mutex::new(RefCell::new(None));
319
+ ///
320
+ /// fn interrupt() {
321
+ /// let mut producer = {
322
+ /// static mut P: Option<Producer<'static, (), 4>> = None;
323
+ /// // SAFETY: Mutable access to `P` is allowed exclusively in this scope
324
+ /// // and `interrupt` cannot be called directly or preempt itself.
325
+ /// unsafe { &mut P }
326
+ /// }
327
+ /// .get_or_insert_with(|| {
328
+ /// critical_section::with(|cs| PRODUCER.borrow_ref_mut(cs).take().unwrap())
329
+ /// });
330
+ ///
331
+ /// producer.enqueue(()).unwrap();
332
+ /// }
333
+ ///
334
+ /// fn main() {
335
+ /// let mut consumer = {
336
+ /// let (p, c) = {
337
+ /// static mut Q: Queue<(), 4> = Queue::new();
338
+ /// // SAFETY: Mutable access to `Q` is allowed exclusively in this scope
339
+ /// // and `main` is only called once.
340
+ /// unsafe { Q.split() }
341
+ /// };
342
+ ///
343
+ /// critical_section::with(move |cs| {
344
+ /// let mut producer = PRODUCER.borrow_ref_mut(cs);
345
+ /// *producer = Some(p);
346
+ /// });
347
+ ///
348
+ /// c
349
+ /// };
350
+ ///
351
+ /// // Interrupt occurs.
352
+ /// # interrupt();
353
+ ///
354
+ /// consumer.dequeue().unwrap();
355
+ /// }
356
+ /// ```
357
+ #[ cfg( not( feature = "nightly" ) ) ]
309
358
pub fn split ( & mut self ) -> ( Producer < ' _ , T , N > , Consumer < ' _ , T , N > ) {
310
359
( Producer { rb : self } , Consumer { rb : self } )
311
360
}
361
+
362
+ /// Splits a queue into producer and consumer endpoints.
363
+ ///
364
+ /// # Examples
365
+ ///
366
+ /// ```
367
+ /// #![feature(const_mut_refs)]
368
+ ///
369
+ /// use core::cell::RefCell;
370
+ ///
371
+ /// use critical_section::Mutex;
372
+ /// use heapless::spsc::{Consumer, Producer, Queue};
373
+ ///
374
+ /// static PC: (
375
+ /// Mutex<RefCell<Option<Producer<'_, (), 4>>>>,
376
+ /// Mutex<RefCell<Option<Consumer<'_, (), 4>>>>,
377
+ /// ) = {
378
+ /// static mut Q: Queue<(), 4> = Queue::new();
379
+ /// // SAFETY: Mutable access to `Q` is allowed exclusively in this scope.
380
+ /// let (p, c) = unsafe { Q.split() };
381
+ ///
382
+ /// (
383
+ /// Mutex::new(RefCell::new(Some(p))),
384
+ /// Mutex::new(RefCell::new(Some(c))),
385
+ /// )
386
+ /// };
387
+ ///
388
+ /// fn interrupt() {
389
+ /// let mut producer = {
390
+ /// static mut P: Option<Producer<'_, (), 4>> = None;
391
+ /// // SAFETY: Mutable access to `P` is allowed exclusively in this scope
392
+ /// // and `interrupt` cannot be called directly or preempt itself.
393
+ /// unsafe { &mut P }
394
+ /// }
395
+ /// .get_or_insert_with(|| {
396
+ /// critical_section::with(|cs| PC.0.borrow_ref_mut(cs).take().unwrap())
397
+ /// });
398
+ ///
399
+ /// producer.enqueue(()).unwrap();
400
+ /// }
401
+ ///
402
+ /// fn main() {
403
+ /// let mut consumer = critical_section::with(|cs| PC.1.borrow_ref_mut(cs).take().unwrap());
404
+ ///
405
+ /// // Interrupt occurs.
406
+ /// # interrupt();
407
+ ///
408
+ /// consumer.dequeue().unwrap();
409
+ /// }
410
+ /// ```
411
+ #[ cfg( feature = "nightly" ) ]
412
+ pub const fn split ( & mut self ) -> ( Producer < ' _ , T , N > , Consumer < ' _ , T , N > ) {
413
+ ( Producer { rb : self } , Consumer { rb : self } )
414
+ }
312
415
}
313
416
314
417
impl < T , const N : usize > Default for Queue < T , N > {
@@ -645,6 +748,36 @@ mod tests {
645
748
// Ensure a `Consumer` containing `!Send` values stays `!Send` itself.
646
749
assert_not_impl_any ! ( Consumer <* const ( ) , 4 >: Send ) ;
647
750
751
+ #[ cfg( feature = "nightly" ) ]
752
+ #[ test]
753
+ fn const_split ( ) {
754
+ use critical_section:: Mutex ;
755
+ use std:: cell:: RefCell ;
756
+
757
+ use super :: { Consumer , Producer } ;
758
+
759
+ static PC : (
760
+ Mutex < RefCell < Option < Producer < ' _ , ( ) , 4 > > > > ,
761
+ Mutex < RefCell < Option < Consumer < ' _ , ( ) , 4 > > > > ,
762
+ ) = {
763
+ static mut Q : Queue < ( ) , 4 > = Queue :: new ( ) ;
764
+ let ( p, c) = unsafe { Q . split ( ) } ;
765
+
766
+ (
767
+ Mutex :: new ( RefCell :: new ( Some ( p) ) ) ,
768
+ Mutex :: new ( RefCell :: new ( Some ( c) ) ) ,
769
+ )
770
+ } ;
771
+ let producer = critical_section:: with ( |cs| PC . 0 . borrow_ref_mut ( cs) . take ( ) . unwrap ( ) ) ;
772
+ let consumer = critical_section:: with ( |cs| PC . 1 . borrow_ref_mut ( cs) . take ( ) . unwrap ( ) ) ;
773
+
774
+ let mut producer: Producer < ' static , ( ) , 4 > = producer;
775
+ let mut consumer: Consumer < ' static , ( ) , 4 > = consumer;
776
+
777
+ assert_eq ! ( producer. enqueue( ( ) ) , Ok ( ( ) ) ) ;
778
+ assert_eq ! ( consumer. dequeue( ) , Some ( ( ) ) ) ;
779
+ }
780
+
648
781
#[ test]
649
782
fn full ( ) {
650
783
let mut rb: Queue < i32 , 3 > = Queue :: new ( ) ;
0 commit comments