jack/
ringbuffer.rs

1use jack_sys as j;
2use std::mem;
3use std::sync::atomic::{AtomicBool, Ordering};
4
5/// A lock-free ringbuffer. The key attribute of a ringbuffer is that it can be safely accessed by
6/// two threads simultaneously, one reading from the buffer and the other writing to it - without
7/// using any synchronization or mutual exclusion primitives.  For this to work correctly, there can
8/// only be a single reader and a single writer thread. Their identities cannot be interchanged.
9///
10/// # Example
11/// ```
12/// let ringbuf = jack::RingBuffer::new(1024).unwrap();
13/// let (mut reader, mut writer) = ringbuf.into_reader_writer();
14///
15/// let buf = [0_u8, 1, 2, 3];
16/// let num = writer.write_buffer(&buf);
17/// assert_eq!(num, buf.len());
18///
19/// // Potentially in a another thread:
20/// let mut outbuf = [0_u8; 8];
21/// let num = reader.read_buffer(&mut outbuf);
22/// ```
23pub struct RingBuffer(*mut j::jack_ringbuffer_t);
24
25impl RingBuffer {
26    /// Allocates a ringbuffer of a specified size.
27    pub fn new(size: usize) -> Result<Self, crate::Error> {
28        let insize = size as libc::size_t;
29        let handle = unsafe { j::jack_ringbuffer_create(insize) };
30
31        if handle.is_null() {
32            return Err(crate::Error::RingbufferCreateFailed);
33        }
34
35        Ok(RingBuffer(handle))
36    }
37
38    /// Lock a ringbuffer data block into memory.
39    pub fn mlock(&mut self) {
40        unsafe { j::jack_ringbuffer_mlock(self.0) };
41    }
42
43    /// Resets the ring buffer, making an empty buffer.
44    pub fn reset(&mut self) {
45        unsafe { j::jack_ringbuffer_reset(self.0) };
46    }
47
48    /// Create a reader and writer, to use the ring buffer.
49    pub fn into_reader_writer(self) -> (RingBufferReader, RingBufferWriter) {
50        let out = unsafe { (RingBufferReader::new(self.0), RingBufferWriter::new(self.0)) };
51        mem::forget(self);
52        out
53    }
54
55    /// Re-create the ring buffer object from reader and writer. useful if you need to call reset.
56    /// The reader and the writer pair must have been created from the same RingBuffer object.  Not
57    /// needed for deallocation, disposing of both reader and writer will deallocate buffer
58    /// resources automatically.
59    ///
60    /// panics if the reader and the writer were created from different RingBuffer objects.
61    pub fn from_reader_writer(r: RingBufferReader, w: RingBufferWriter) -> Self {
62        if r.ringbuffer_handle != w.ringbuffer_handle {
63            // drops will be valid during unwinding - assuming that all reader/writer pairs are
64            // consisitent.
65            panic!("mismatching read and write handles!")
66        }
67
68        // The next 3 lines transfer ownership of the ringbuffer from both reader and writer to the
69        // new buffer object.
70        let handle = RingBuffer(r.ringbuffer_handle);
71        mem::forget(r);
72        mem::forget(w);
73
74        handle
75    }
76}
77
78impl Drop for RingBuffer {
79    fn drop(&mut self) {
80        if !self.0.is_null() {
81            unsafe { j::jack_ringbuffer_free(self.0) };
82        }
83        self.0 = std::ptr::null_mut();
84    }
85}
86
87unsafe impl Send for RingBuffer {}
88unsafe impl Sync for RingBuffer {}
89
90/// Read end of the ring buffer. Can only be used from one thread (can be different from the write
91/// thread).
92pub struct RingBufferReader {
93    ringbuffer_handle: *mut j::jack_ringbuffer_t,
94    /// A marker to check if both halves of the ringbuffer are live. Destroying a ringbuffer is not
95    /// a realtime operation.
96    both_live: AtomicBool,
97}
98
99unsafe impl Send for RingBufferReader {}
100unsafe impl Sync for RingBufferReader {}
101
102/// Write end of the ring buffer. Can only be used from one thread (can be a different from the read
103/// thread).
104pub struct RingBufferWriter {
105    ringbuffer_handle: *mut j::jack_ringbuffer_t,
106    both_live: AtomicBool,
107}
108
109unsafe impl Send for RingBufferWriter {}
110unsafe impl Sync for RingBufferWriter {}
111
112impl RingBufferReader {
113    // safety: this method must be called as part of the splitting of the ringbuffer into 2
114    // channels.
115    unsafe fn new(raw: *mut j::jack_ringbuffer_t) -> Self {
116        RingBufferReader {
117            ringbuffer_handle: raw,
118            both_live: AtomicBool::new(true),
119        }
120    }
121
122    /// Fill a data structure with a description of the current readable data held in the
123    /// ringbuffer. This description is returned in a two slices. Two slices are needed because the
124    /// data to be read may be split across the end of the ringbuffer. The first slice represents
125    /// the bytes ready to be read. If the second slice is not empty, it is the continuation of the
126    /// data that ended in the first slices. For convenience, consider using peek_iter instead.
127    pub fn get_vector(&self) -> (&[u8], &[u8]) {
128        let mut vec = [
129            j::jack_ringbuffer_data_t::default(),
130            j::jack_ringbuffer_data_t::default(),
131        ];
132        let vecstart = &mut vec[0] as *mut j::jack_ringbuffer_data_t;
133
134        unsafe { j::jack_ringbuffer_get_read_vector(self.ringbuffer_handle, vecstart) };
135
136        let view1 = vec[0];
137        let view2 = vec[1];
138
139        let buf1 = view1.buf as *mut u8;
140        let len1 = view1.len;
141
142        let mut buf2 = view2.buf as *mut u8;
143        let len2 = view2.len;
144
145        if len2 == 0 {
146            // buf2 can't be null even if length is zero, so just use buf1
147            buf2 = buf1;
148        }
149
150        let view1 = unsafe { std::slice::from_raw_parts(buf1, len1) };
151        let view2 = unsafe { std::slice::from_raw_parts(buf2, len2) };
152        (view1, view2)
153    }
154
155    /// Read data from the ringbuffer. Returns the number of bytes read, which may range from 0 to
156    /// buf.len().
157    pub fn read_buffer(&mut self, buf: &mut [u8]) -> usize {
158        if buf.is_empty() {
159            return 0;
160        }
161
162        let insize: libc::size_t = buf.len() as libc::size_t;
163        let bufstart = &mut buf[0] as *mut _ as *mut libc::c_char;
164
165        unsafe { j::jack_ringbuffer_read(self.ringbuffer_handle, bufstart, insize) }
166    }
167
168    /// Read data from the ringbuffer. Returns the slice that was read into. This is a subset of `buf`.
169    pub fn read_slice<'a>(&mut self, buf: &'a mut [u8]) -> &'a [u8] {
170        let len = self.read_buffer(buf);
171        &buf[0..len]
172    }
173
174    /// Read data from the ringbuffer. Opposed to read_buffer() this function does not move the read
175    /// pointer.  Thus it's a convenient way to inspect data in the ringbuffer in a continous
176    /// fashion.  The price is that the data is copied into a user provided buffer.  For "raw"
177    /// non-copy inspection of the data in the ringbuffer use get_vector() or peek_iter.  Returns:
178    /// the number of bytes read, which may range from 0 to buf.len()
179    pub fn peek(&self, buf: &mut [u8]) -> usize {
180        if buf.is_empty() {
181            return 0;
182        }
183
184        let insize: libc::size_t = buf.len() as libc::size_t;
185        let bufstart = &mut buf[0] as *mut _ as *mut libc::c_char;
186
187        unsafe { j::jack_ringbuffer_peek(self.ringbuffer_handle, bufstart, insize) }
188    }
189
190    /// Advance the read pointer. use this after peek/peek_iter or get_vector to advance the buffer
191    /// pointer.
192    pub fn advance(&mut self, cnt: usize) {
193        let incnt = cnt as libc::size_t;
194        unsafe { j::jack_ringbuffer_read_advance(self.ringbuffer_handle, incnt) };
195    }
196
197    /// Return the number of bytes available for reading.
198    pub fn space(&self) -> usize {
199        unsafe { j::jack_ringbuffer_read_space(self.ringbuffer_handle) }
200    }
201
202    /// Iterator that goes over all the data available to read.
203    pub fn peek_iter(
204        &'_ self,
205    ) -> std::iter::Chain<std::slice::Iter<'_, u8>, std::slice::Iter<'_, u8>> {
206        let (view1, view2) = self.get_vector();
207
208        view1.iter().chain(view2.iter())
209    }
210}
211
212impl std::io::Read for RingBufferReader {
213    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
214        Ok(self.read_buffer(buf))
215    }
216}
217
218impl Drop for RingBufferReader {
219    fn drop(&mut self) {
220        match self
221            .both_live
222            .compare_exchange(true, false, Ordering::SeqCst, Ordering::SeqCst)
223        {
224            Ok(false) | Err(false) => {
225                drop(RingBuffer(self.ringbuffer_handle));
226            }
227            _ => (),
228        }
229    }
230}
231
232impl RingBufferWriter {
233    // safety: this method must be called as part of the splitting of the ringbuffer into 2
234    // channels.
235    unsafe fn new(raw: *mut j::jack_ringbuffer_t) -> Self {
236        RingBufferWriter {
237            ringbuffer_handle: raw,
238            both_live: AtomicBool::new(true),
239        }
240    }
241
242    /// Write data into the ringbuffer.  Returns: The number of bytes written, which may range from
243    /// 0 to buf.len()
244    pub fn write_buffer(&mut self, buf: &[u8]) -> usize {
245        if buf.is_empty() {
246            return 0;
247        }
248
249        let insize: libc::size_t = buf.len() as libc::size_t;
250        let bufstart = &buf[0] as *const _ as *const libc::c_char;
251
252        unsafe { j::jack_ringbuffer_write(self.ringbuffer_handle, bufstart, insize) }
253    }
254
255    /// Advance the write pointer. use this after peek_iter or get_vector to advance the buffer
256    /// pointer.
257    pub fn advance(&mut self, cnt: usize) {
258        let incnt = cnt as libc::size_t;
259        unsafe { j::jack_ringbuffer_write_advance(self.ringbuffer_handle, incnt) };
260    }
261
262    /// Return the number of bytes available for writing.
263    pub fn space(&mut self) -> usize {
264        unsafe { j::jack_ringbuffer_write_space(self.ringbuffer_handle) }
265    }
266
267    /// Return a pair of slices of the current writable space in the ringbuffer. two slices are
268    /// needed because the space available for writing may be split across the end of the
269    /// ringbuffer. Consider using peek_iter for convenience.
270    pub fn get_vector(&mut self) -> (&mut [u8], &mut [u8]) {
271        let mut vec = [
272            j::jack_ringbuffer_data_t::default(),
273            j::jack_ringbuffer_data_t::default(),
274        ];
275        let vecstart = &mut vec[0] as *mut j::jack_ringbuffer_data_t;
276
277        unsafe { j::jack_ringbuffer_get_write_vector(self.ringbuffer_handle, vecstart) };
278
279        let view1 = vec[0];
280        let view2 = vec[1];
281
282        let buf1 = view1.buf as *mut u8;
283        let len1 = view1.len;
284
285        let mut buf2 = view2.buf as *mut u8;
286        let len2 = view2.len;
287
288        if len2 == 0 {
289            // buf2 can't be null even if length is zero, so just use buf1
290            buf2 = buf1;
291        }
292
293        let view1 = unsafe { std::slice::from_raw_parts_mut(buf1, len1) };
294        let view2 = unsafe { std::slice::from_raw_parts_mut(buf2, len2) };
295        (view1, view2)
296    }
297
298    /// Iterator that goes over all the data available to write.
299    pub fn peek_iter(
300        &'_ mut self,
301    ) -> std::iter::Chain<std::slice::IterMut<'_, u8>, std::slice::IterMut<'_, u8>> {
302        let (view1, view2) = self.get_vector();
303
304        view1.iter_mut().chain(view2.iter_mut())
305    }
306}
307
308impl std::io::Write for RingBufferWriter {
309    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
310        Ok(self.write_buffer(buf))
311    }
312
313    fn flush(&mut self) -> std::io::Result<()> {
314        Ok(())
315    }
316}
317
318impl Drop for RingBufferWriter {
319    fn drop(&mut self) {
320        match self
321            .both_live
322            .compare_exchange(true, false, Ordering::SeqCst, Ordering::SeqCst)
323        {
324            Ok(false) | Err(false) => {
325                drop(RingBuffer(self.ringbuffer_handle));
326            }
327            _ => (),
328        }
329    }
330}