Struct rtrb::Producer

source ·
pub struct Producer<T> { /* private fields */ }
Expand description

The producer side of a RingBuffer.

Can be moved between threads, but references from different threads are not allowed (i.e. it is Send but not Sync).

Can only be created with RingBuffer::new() (together with its counterpart, the Consumer).

Individual elements can be moved into the ring buffer with Producer::push(), multiple elements at once can be written with Producer::write_chunk() and Producer::write_chunk_uninit().

The number of free slots currently available for writing can be obtained with Producer::slots().

When the Producer is dropped, Consumer::is_abandoned() will return true. This can be used as a crude way to communicate to the receiving thread that no more data will be produced. When the Producer is dropped after the Consumer has already been dropped, RingBuffer::drop() will be called, freeing the allocated memory.

Implementations§

source§

impl<T> Producer<T>

source

pub fn write_chunk(&mut self, n: usize) -> Result<WriteChunk<'_, T>, ChunkError>
where T: Default,

Returns n slots (initially containing their Default value) for writing.

WriteChunk::as_mut_slices() provides mutable access to the slots. After writing to those slots, they explicitly have to be made available to be read by the Consumer by calling WriteChunk::commit() or WriteChunk::commit_all().

For an alternative that does not require the trait bound Default, see Producer::write_chunk_uninit().

If items are supposed to be moved from an iterator into the ring buffer, Producer::write_chunk_uninit() followed by WriteChunkUninit::fill_from_iter() can be used.

§Errors

If not enough slots are available, an error (containing the number of available slots) is returned. Use Producer::slots() to obtain the number of available slots beforehand.

§Examples

See the documentation of the chunks module.

source

pub fn write_chunk_uninit( &mut self, n: usize ) -> Result<WriteChunkUninit<'_, T>, ChunkError>

Returns n (uninitialized) slots for writing.

WriteChunkUninit::as_mut_slices() provides mutable access to the uninitialized slots. After writing to those slots, they explicitly have to be made available to be read by the Consumer by calling WriteChunkUninit::commit() or WriteChunkUninit::commit_all().

Alternatively, WriteChunkUninit::fill_from_iter() can be used to move items from an iterator into the available slots. All moved items are automatically made available to be read by the Consumer.

§Errors

If not enough slots are available, an error (containing the number of available slots) is returned. Use Producer::slots() to obtain the number of available slots beforehand.

§Safety

This function itself is safe, as is WriteChunkUninit::fill_from_iter(). However, when using WriteChunkUninit::as_mut_slices(), the user has to make sure that the relevant slots have been initialized before calling WriteChunkUninit::commit() or WriteChunkUninit::commit_all().

For a safe alternative that provides mutable slices of Default-initialized slots, see Producer::write_chunk().

source§

impl<T> Producer<T>

source

pub fn push(&mut self, value: T) -> Result<(), PushError<T>>

Attempts to push an element into the queue.

The element is moved into the ring buffer and its slot is made available to be read by the Consumer.

§Errors

If the queue is full, the element is returned back as an error.

§Examples
use rtrb::{RingBuffer, PushError};

let (mut p, c) = RingBuffer::new(1);

assert_eq!(p.push(10), Ok(()));
assert_eq!(p.push(20), Err(PushError::Full(20)));
source

pub fn slots(&self) -> usize

Returns the number of slots available for writing.

Since items can be concurrently consumed on another thread, the actual number of available slots may increase at any time (up to the RingBuffer::capacity()).

To check for a single available slot, using Producer::is_full() is often quicker (because it might not have to check an atomic variable).

§Examples
use rtrb::RingBuffer;

let (p, c) = RingBuffer::<f32>::new(1024);

assert_eq!(p.slots(), 1024);
source

pub fn is_full(&self) -> bool

Returns true if there are currently no slots available for writing.

A full ring buffer might cease to be full at any time if the corresponding Consumer is consuming items in another thread.

§Examples
use rtrb::RingBuffer;

let (p, c) = RingBuffer::<f32>::new(1);

assert!(!p.is_full());

Since items can be concurrently consumed on another thread, the ring buffer might not be full for long:

if p.is_full() {
    // The buffer might be full, but it might as well not be
    // if an item was just consumed on another thread.
}

However, if it’s not full, another thread cannot change that:

if !p.is_full() {
    // At least one slot is guaranteed to be available for writing.
}
source

pub fn is_abandoned(&self) -> bool

Returns true if the corresponding Consumer has been destroyed.

Note that since Rust version 1.74.0, this is not synchronizing with the consumer thread anymore, see https://github.com/mgeier/rtrb/issues/114. In a future version of rtrb, the synchronizing behavior might be restored.

§Examples
use rtrb::RingBuffer;

let (mut p, c) = RingBuffer::new(7);
assert!(!p.is_abandoned());
assert_eq!(p.push(10), Ok(()));
drop(c);
// The items that are still in the ring buffer are not accessible anymore.
assert!(p.is_abandoned());
// Even though it's futile, items can still be written:
assert_eq!(p.push(11), Ok(()));

Since the consumer can be concurrently dropped on another thread, the producer might become abandoned at any time:

if !p.is_abandoned() {
    // Right now, the consumer might still be alive, but it might as well not be
    // if another thread has just dropped it.
}

However, if it already is abandoned, it will stay that way:

if p.is_abandoned() {
    // This is needed since Rust 1.74.0, see https://github.com/mgeier/rtrb/issues/114:
    std::sync::atomic::fence(std::sync::atomic::Ordering::Acquire);
    // The consumer does definitely not exist anymore.
}
source

pub fn buffer(&self) -> &RingBuffer<T>

Returns a read-only reference to the ring buffer.

Trait Implementations§

source§

impl<T: Debug> Debug for Producer<T>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<T: PartialEq> PartialEq for Producer<T>

source§

fn eq(&self, other: &Producer<T>) -> bool

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
source§

impl Write for Producer<u8>

source§

fn write(&mut self, buf: &[u8]) -> Result<usize>

Write a buffer into this writer, returning how many bytes were written. Read more
source§

fn flush(&mut self) -> Result<()>

Flush this output stream, ensuring that all intermediately buffered contents reach their destination. Read more
1.36.0 · source§

fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> Result<usize, Error>

Like write, except that it writes from a slice of buffers. Read more
source§

fn is_write_vectored(&self) -> bool

🔬This is a nightly-only experimental API. (can_vector)
Determines if this Writer has an efficient write_vectored implementation. Read more
1.0.0 · source§

fn write_all(&mut self, buf: &[u8]) -> Result<(), Error>

Attempts to write an entire buffer into this writer. Read more
source§

fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> Result<(), Error>

🔬This is a nightly-only experimental API. (write_all_vectored)
Attempts to write multiple buffers into this writer. Read more
1.0.0 · source§

fn write_fmt(&mut self, fmt: Arguments<'_>) -> Result<(), Error>

Writes a formatted string into this writer, returning any error encountered. Read more
1.0.0 · source§

fn by_ref(&mut self) -> &mut Self
where Self: Sized,

Creates a “by reference” adapter for this instance of Write. Read more
source§

impl<T: Eq> Eq for Producer<T>

source§

impl<T: Send> Send for Producer<T>

source§

impl<T> StructuralPartialEq for Producer<T>

Auto Trait Implementations§

§

impl<T> !Freeze for Producer<T>

§

impl<T> !RefUnwindSafe for Producer<T>

§

impl<T> !Sync for Producer<T>

§

impl<T> Unpin for Producer<T>

§

impl<T> UnwindSafe for Producer<T>
where T: RefUnwindSafe,

Blanket Implementations§

source§

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

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

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

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

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

source§

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

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

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

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 T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

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

Performs the conversion.
source§

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

§

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

The type returned in the event of a conversion error.
source§

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

Performs the conversion.