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>
impl<T> Producer<T>
sourcepub fn write_chunk(&mut self, n: usize) -> Result<WriteChunk<'_, T>, ChunkError>where
T: Default,
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.
sourcepub fn write_chunk_uninit(
&mut self,
n: usize
) -> Result<WriteChunkUninit<'_, T>, ChunkError>
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>
impl<T> Producer<T>
sourcepub fn push(&mut self, value: T) -> Result<(), PushError<T>>
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)));
sourcepub fn slots(&self) -> usize
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);
sourcepub fn is_full(&self) -> bool
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.
}
sourcepub fn is_abandoned(&self) -> bool
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.
}
sourcepub fn buffer(&self) -> &RingBuffer<T>
pub fn buffer(&self) -> &RingBuffer<T>
Returns a read-only reference to the ring buffer.
Trait Implementations§
source§impl<T: PartialEq> PartialEq for Producer<T>
impl<T: PartialEq> PartialEq for Producer<T>
source§impl Write for Producer<u8>
impl Write for Producer<u8>
source§fn write(&mut self, buf: &[u8]) -> Result<usize>
fn write(&mut self, buf: &[u8]) -> Result<usize>
source§fn flush(&mut self) -> Result<()>
fn flush(&mut self) -> Result<()>
source§fn is_write_vectored(&self) -> bool
fn is_write_vectored(&self) -> bool
can_vector
)1.0.0 · source§fn write_all(&mut self, buf: &[u8]) -> Result<(), Error>
fn write_all(&mut self, buf: &[u8]) -> Result<(), Error>
source§fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> Result<(), Error>
fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> Result<(), Error>
write_all_vectored
)