spsc_ringbuf_core/
ringbuf.rs1use 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 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 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 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}