spsc_ringbuf_core/
ringbuf.rs

1use crate::ringbuf_ref::{ErrCode, RingBufRef};
2use core::cell::Cell;
3
4
5pub struct Producer <'a,T, const N: usize> {
6
7    inner: &'a RingBufRef<T, N>
8
9}
10
11impl<'a, T, const N: usize> Producer<'a, T, N> {
12
13    #[inline(always)]
14    pub fn writer_front(&mut self) -> Option<&mut T> { 
15        self.inner.writer_front()
16    }
17
18
19    #[inline(always)]
20    pub fn commit(&mut self) -> Result<(), ErrCode> { 
21        self.inner.commit()
22    }
23}
24
25pub struct Consumer <'a,T, const N: usize> {
26
27    inner: &'a RingBufRef<T, N>
28
29}
30
31impl<'a, T, const N: usize> Consumer<'a, T, N> {
32
33    #[inline(always)]
34    pub fn reader_front(&self) -> Option<&T> {
35        self.inner.reader_front()
36
37    }
38    
39    #[inline(always)]
40    pub fn reader_front_mut(&mut self) -> Option<&mut T> {
41
42        self.inner.reader_front_mut()
43
44    }
45
46
47    #[inline(always)]
48    pub fn pop(&mut self) -> Result<(), ErrCode> {
49        self.inner.pop()
50    }
51}
52
53
54pub struct RingBuf<T, const N: usize> {
55
56    ringbuf_ref: RingBufRef<T, N>,
57    has_split_prod: Cell<bool>,
58    has_split_cons: Cell<bool>
59
60}
61
62impl<T, const N: usize> RingBuf<T, N> {
63
64    pub const INIT_0: RingBuf<T, N> = Self::new();
65
66    pub const fn new() -> Self {
67        RingBuf {
68            ringbuf_ref: RingBufRef::new(),
69            has_split_prod: Cell::new(false),
70            has_split_cons: Cell::new(false)
71        }
72    }
73    pub fn has_split_prod(&self) -> bool {
74        self.has_split_prod.get()
75    }
76    pub fn has_split_cons(&self) -> bool {
77        self.has_split_cons.get()
78    }
79    pub fn has_split(&self) -> bool {
80        self.has_split_cons() || self.has_split_prod()
81    }
82
83    
84    pub fn split_prod(&self) -> Result<Producer<'_, T, N>, ()> {
85
86        if self.has_split_prod.get() {
87            // Can only split once in life time
88            Err(())
89        }
90        else {
91            let producer = Producer {inner: &self.ringbuf_ref};
92            self.has_split_prod.set(true);
93            Ok(producer)
94        }
95    }
96    pub fn split_cons(&self) -> Result<Consumer<'_, T, N>, ()> {
97
98        if self.has_split_cons.get() {
99            // Can only split once in life time
100            Err(())
101        }
102        else {
103            let consumer = Consumer {inner: &self.ringbuf_ref};
104            self.has_split_cons.set(true);
105            Ok(consumer)
106        }
107    }
108    pub fn split(&self) -> Result<(Producer<'_, T, N>, Consumer<'_, T, N>), ()> {
109
110        match (self.split_prod(), self.split_cons())  {
111            (Ok(prod), Ok(cons)) => Ok((prod, cons)),
112            _ => Err(())
113        }
114    }
115    pub fn len(&self) -> u32 {
116        self.ringbuf_ref.len()
117    }
118
119}
120
121#[cfg(test)]
122mod tests {
123    use super::*;
124    #[test]
125    fn test_mut_split() {
126        
127        let ringbuf = RingBuf::<u32, 4>::new();
128
129        // The producer and consumer must be mutable to use the mut functions such
130        // as stage, commit and pop
131        if let Ok((mut producer, mut consumer)) = ringbuf.split() {
132            
133            let loc = producer.writer_front();
134
135            if let Some(v) = loc {
136                *v = 42;
137
138                assert!(producer.commit().is_ok());
139            }
140
141            assert!(consumer.reader_front().is_some());
142
143            assert!(*consumer.reader_front().unwrap() == 42);
144
145            assert!(consumer.pop().is_ok());
146
147        }
148        else {
149            panic!("first split failed!");
150        }
151
152        assert!(ringbuf.split().is_err());
153    }
154}