pub struct SharedRb<T, C: Container<T>> { /* private fields */ }
Expand description

Ring buffer that could be shared between threads.

Implements Sync if T implements Send. And therefore its Producer and Consumer implement Send.

Note that there is no explicit requirement of T: Send. Instead SharedRb will work just fine even with T: !Send until you try to send its Producer or Consumer to another thread.

use std::{thread, vec::Vec};
use ringbuf::SharedRb;

let (mut prod, mut cons) = SharedRb::<i32, Vec<_>>::new(256).split();
thread::spawn(move || {
    prod.push(123).unwrap();
})
.join();
thread::spawn(move || {
    assert_eq!(cons.pop().unwrap(), 123);
})
.join();

Implementations§

source§

impl<T> SharedRb<T, Vec<MaybeUninit<T>>>

source

pub fn new(capacity: usize) -> Self

Creates a new instance of a ring buffer.

Panics if allocation failed or capacity is zero.

Examples found in repository?
examples/overwrite.rs (line 4)
3
4
5
6
7
8
9
10
11
12
13
fn main() {
    let mut rb = HeapRb::<i32>::new(2);

    assert_eq!(rb.push_overwrite(0), None);
    assert_eq!(rb.push_overwrite(1), None);
    assert_eq!(rb.push_overwrite(2), Some(0));

    assert_eq!(rb.pop(), Some(1));
    assert_eq!(rb.pop(), Some(2));
    assert_eq!(rb.pop(), None);
}
More examples
Hide additional examples
examples/simple.rs (line 4)
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
fn main() {
    let rb = HeapRb::<i32>::new(2);
    let (mut prod, mut cons) = rb.split();

    prod.push(0).unwrap();
    prod.push(1).unwrap();
    assert_eq!(prod.push(2), Err(2));

    assert_eq!(cons.pop().unwrap(), 0);

    prod.push(2).unwrap();

    assert_eq!(cons.pop().unwrap(), 1);
    assert_eq!(cons.pop().unwrap(), 2);
    assert_eq!(cons.pop(), None);
}
examples/message.rs (line 6)
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
fn main() {
    let buf = HeapRb::<u8>::new(10);
    let (mut prod, mut cons) = buf.split();

    let smsg = "The quick brown fox jumps over the lazy dog";

    let pjh = thread::spawn(move || {
        println!("-> sending message: '{}'", smsg);

        let zero = [0];
        let mut bytes = smsg.as_bytes().chain(&zero[..]);
        loop {
            if prod.is_full() {
                println!("-> buffer is full, waiting");
                thread::sleep(Duration::from_millis(1));
            } else {
                let n = prod.read_from(&mut bytes, None).unwrap();
                if n == 0 {
                    break;
                }
                println!("-> {} bytes sent", n);
            }
        }

        println!("-> message sent");
    });

    let cjh = thread::spawn(move || {
        println!("<- receiving message");

        let mut bytes = Vec::<u8>::new();
        loop {
            if cons.is_empty() {
                if bytes.ends_with(&[0]) {
                    break;
                } else {
                    println!("<- buffer is empty, waiting");
                    thread::sleep(Duration::from_millis(1));
                }
            } else {
                let n = cons.write_into(&mut bytes, None).unwrap();
                println!("<- {} bytes received", n);
            }
        }

        assert_eq!(bytes.pop().unwrap(), 0);
        let msg = String::from_utf8(bytes).unwrap();
        println!("<- message received: '{}'", msg);

        msg
    });

    pjh.join().unwrap();
    let rmsg = cjh.join().unwrap();

    assert_eq!(smsg, rmsg);
}
source

pub fn try_new(capacity: usize) -> Result<Self, TryReserveError>

Creates a new instance of a ring buffer returning an error if allocation failed.

Panics if capacity is zero.

source§

impl<T, C: Container<T>> SharedRb<T, C>

source

pub unsafe fn from_raw_parts(container: C, head: usize, tail: usize) -> Self

Constructs ring buffer from container and counters.

Safety

The items in container inside head..tail range must be initialized, items outside this range must be uninitialized. head and tail values must be valid (see RbBase).

source

pub unsafe fn into_raw_parts(self) -> (C, usize, usize)

Destructures ring buffer into underlying container and head and tail counters.

Safety

Initialized contents of the container must be properly dropped.

source

pub fn split(self) -> (Producer<T, Arc<Self>>, Consumer<T, Arc<Self>>)where Self: Sized,

Splits ring buffer into producer and consumer.

This method consumes the ring buffer and puts it on heap in Arc. If you don’t want to use heap the see Self::split_ref.

Examples found in repository?
examples/simple.rs (line 5)
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
fn main() {
    let rb = HeapRb::<i32>::new(2);
    let (mut prod, mut cons) = rb.split();

    prod.push(0).unwrap();
    prod.push(1).unwrap();
    assert_eq!(prod.push(2), Err(2));

    assert_eq!(cons.pop().unwrap(), 0);

    prod.push(2).unwrap();

    assert_eq!(cons.pop().unwrap(), 1);
    assert_eq!(cons.pop().unwrap(), 2);
    assert_eq!(cons.pop(), None);
}
More examples
Hide additional examples
examples/message.rs (line 7)
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
fn main() {
    let buf = HeapRb::<u8>::new(10);
    let (mut prod, mut cons) = buf.split();

    let smsg = "The quick brown fox jumps over the lazy dog";

    let pjh = thread::spawn(move || {
        println!("-> sending message: '{}'", smsg);

        let zero = [0];
        let mut bytes = smsg.as_bytes().chain(&zero[..]);
        loop {
            if prod.is_full() {
                println!("-> buffer is full, waiting");
                thread::sleep(Duration::from_millis(1));
            } else {
                let n = prod.read_from(&mut bytes, None).unwrap();
                if n == 0 {
                    break;
                }
                println!("-> {} bytes sent", n);
            }
        }

        println!("-> message sent");
    });

    let cjh = thread::spawn(move || {
        println!("<- receiving message");

        let mut bytes = Vec::<u8>::new();
        loop {
            if cons.is_empty() {
                if bytes.ends_with(&[0]) {
                    break;
                } else {
                    println!("<- buffer is empty, waiting");
                    thread::sleep(Duration::from_millis(1));
                }
            } else {
                let n = cons.write_into(&mut bytes, None).unwrap();
                println!("<- {} bytes received", n);
            }
        }

        assert_eq!(bytes.pop().unwrap(), 0);
        let msg = String::from_utf8(bytes).unwrap();
        println!("<- message received: '{}'", msg);

        msg
    });

    pjh.join().unwrap();
    let rmsg = cjh.join().unwrap();

    assert_eq!(smsg, rmsg);
}
source

pub fn split_ref(&mut self) -> (Producer<T, &Self>, Consumer<T, &Self>)where Self: Sized,

Splits ring buffer into producer and consumer without using the heap.

In this case producer and consumer stores a reference to the ring buffer, so you also need to store the buffer somewhere.

Examples found in repository?
examples/static.rs (line 8)
5
6
7
8
9
10
11
12
13
14
15
fn main() {
    const RB_SIZE: usize = 1;
    let mut rb = StaticRb::<i32, RB_SIZE>::default();
    let (mut prod, mut cons) = rb.split_ref();

    assert_eq!(prod.push(123), Ok(()));
    assert_eq!(prod.push(321), Err(321));

    assert_eq!(cons.pop(), Some(123));
    assert_eq!(cons.pop(), None);
}

Trait Implementations§

source§

impl<T, const N: usize> Default for SharedRb<T, [MaybeUninit<T>; N]>

source§

fn default() -> Self

Returns the “default value” for a type. Read more
source§

impl<T, C: Container<T>> Drop for SharedRb<T, C>

source§

fn drop(&mut self)

Executes the destructor for this type. Read more
source§

impl<T, C: Container<T>> Rb<T> for SharedRb<T, C>

source§

fn capacity(&self) -> usize

Returns capacity of the ring buffer. Read more
source§

fn len(&self) -> usize

The number of items stored in the ring buffer.
source§

fn free_len(&self) -> usize

The number of remaining free places in the buffer.
source§

fn as_slices(&self) -> (&[T], &[T])

Returns a pair of slices which contain, in order, the contents of the ring buffer.
source§

fn as_mut_slices(&mut self) -> (&mut [T], &mut [T])

Returns a pair of mutable slices which contain, in order, the contents of the ring buffer.
source§

fn pop(&mut self) -> Option<T>

Removes latest item from the ring buffer and returns it. Read more
source§

fn pop_iter(&mut self) -> PopIterator<'_, T, RbWrap<Self>>

Returns an iterator that removes items one by one from the ring buffer.
source§

fn iter(&self) -> Chain<Iter<'_, T>, Iter<'_, T>>

Returns a front-to-back iterator containing references to items in the ring buffer. Read more
source§

fn iter_mut(&mut self) -> Chain<IterMut<'_, T>, IterMut<'_, T>>

Returns a front-to-back iterator that returns mutable references to items in the ring buffer. Read more
source§

fn skip(&mut self, count: usize) -> usize

Removes exactly n items from the buffer and safely drops them. Read more
source§

fn clear(&mut self) -> usize

Removes all items from the buffer and safely drops them. Read more
source§

fn push(&mut self, elem: T) -> Result<(), T>

Appends an item to the ring buffer. Read more
source§

fn push_overwrite(&mut self, elem: T) -> Option<T>

Pushes an item to the ring buffer overwriting the latest item if the buffer is full. Read more
source§

fn push_iter<I: Iterator<Item = T>>(&mut self, iter: &mut I)

Appends items from an iterator to the ring buffer. Elements that haven’t been added to the ring buffer remain in the iterator.
source§

fn push_iter_overwrite<I: Iterator<Item = T>>(&mut self, iter: I)

Appends items from an iterator to the ring buffer. Read more
source§

impl<T, C: Container<T>> RbBase<T> for SharedRb<T, C>

source§

unsafe fn slices( &self, head: usize, tail: usize ) -> (&mut [MaybeUninit<T>], &mut [MaybeUninit<T>])

Returns part of underlying raw ring buffer memory as slices. Read more
source§

fn capacity_nonzero(&self) -> NonZeroUsize

Capacity of the ring buffer. Read more
source§

fn head(&self) -> usize

Head position.
source§

fn tail(&self) -> usize

Tail position.
source§

fn modulus(&self) -> NonZeroUsize

Modulus for head and tail values. Read more
source§

fn occupied_len(&self) -> usize

The number of items stored in the buffer at the moment.
source§

fn vacant_len(&self) -> usize

The number of vacant places in the buffer at the moment.
source§

fn is_empty(&self) -> bool

Checks if the occupied range is empty.
source§

fn is_full(&self) -> bool

Checks if the vacant range is empty.
source§

impl<T, C: Container<T>> RbRead<T> for SharedRb<T, C>

source§

unsafe fn set_head(&self, value: usize)

Sets the new head position. Read more
source§

unsafe fn advance_head(&self, count: usize)

Move head position by count items forward. Read more
source§

fn occupied_ranges(&self) -> (Range<usize>, Range<usize>)

Returns a pair of ranges of Self::occupied_slices location in underlying container.
source§

unsafe fn occupied_slices( &self ) -> (&mut [MaybeUninit<T>], &mut [MaybeUninit<T>])

Provides a direct mutable access to the ring buffer occupied memory. Read more
source§

unsafe fn skip_internal(&self, count_or_all: Option<usize>) -> usize

Removes items from the head of ring buffer and drops them. Read more
source§

impl<T, C: Container<T>> RbWrite<T> for SharedRb<T, C>

source§

unsafe fn set_tail(&self, value: usize)

Sets the new tail position. Read more
source§

unsafe fn advance_tail(&self, count: usize)

Move tail position by count items forward. Read more
source§

fn vacant_ranges(&self) -> (Range<usize>, Range<usize>)

Returns a pair of ranges of Self::vacant_slices location in underlying container.
source§

unsafe fn vacant_slices(&self) -> (&mut [MaybeUninit<T>], &mut [MaybeUninit<T>])

Provides a direct access to the ring buffer vacant memory. Returns a pair of slices of uninitialized memory, the second one may be empty. Read more

Auto Trait Implementations§

§

impl<T, C> RefUnwindSafe for SharedRb<T, C>where T: RefUnwindSafe, <C as Container<T>>::Internal: RefUnwindSafe,

§

impl<T, C> Send for SharedRb<T, C>where T: Send, <C as Container<T>>::Internal: Send,

§

impl<T, C> Sync for SharedRb<T, C>where T: Send,

§

impl<T, C> Unpin for SharedRb<T, C>where T: Unpin, <C as Container<T>>::Internal: Unpin,

§

impl<T, C> UnwindSafe for SharedRb<T, C>where T: UnwindSafe, <C as Container<T>>::Internal: UnwindSafe,

Blanket Implementations§

source§

impl<T> Any for Twhere T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for Twhere T: ?Sized,

const: unstable · source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere T: ?Sized,

const: unstable · source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

const: unstable · source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for Twhere U: From<T>,

const: unstable · source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T, U> TryFrom<U> for Twhere U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
const: unstable · source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for Twhere U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
const: unstable · source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.