pub struct ProdIter<'buf, B: MutRB> { /* private fields */ }Expand description
Iterator used to push data into the buffer.
When working with types which implement both
Copy and
Clone traits, copy methods should be
preferred over clone methods.
§TL;DR about uninitialised memory
If you created the buffer with either default or from methods and you are not going to use ConsIter::pop,
then it is safe to use normal methods from this struct.
If you either created the buffer with new_zeroed or are going to move items out of the buffer (e.g. using ConsIter::pop),
then you must pay attention to what you do and ensure that all the locations cleared by pop will be re-filled with *_init methods.
After that you can use normal methods again.
Read below to know why and how.
It would be a good idea to do a check with miri, which is able to tell if and when something bad has happened.
§A note about how this buffer is made:
Every element in this buffer is wrapped in an UnsafeSyncCell, which in the end is a MaybeUninit.
MaybeUninit (read the official docs if you want to know more) is a way to deal with possibly uninitialised data.
When one creates a buffer from this crate, they may choose to build it either with default and from methods,
or with new_zeroed ones.
When using the former, an initialised buffer is created, so there are no problems concerning uninitialised memory.
With the latter methods, a zeroed buffer is rather created.
To write data into an uninitialised (or zeroed) block of memory, one has to use write
method, which overwrites a memory location, without reading or dropping the old value.
Remember that a zeroed location must never be read or dropped. Doing so would cause UB!
On the other hand, using write on an initialised block doesn’t drop the old value, causing then a memory leak.
For each of the methods in this struct, there exists a *_init one (e.g. Self::push and Self::push_init).
Normal methods are faster than *_init ones, and should be preferred over these when dealing with surely
initialised memory.
On the other hand, *_init methods always perform a check over the memory they are going to write and choose the proper way to
deal it, even dropping the old value, if there is the need. So they are safe to use upon a possibly uninitialised block.
Implementations§
Source§impl<'buf, B: MutRB<Item = T>, T> ProdIter<'buf, B>
impl<'buf, B: MutRB<Item = T>, T> ProdIter<'buf, B>
Sourcepub fn push(&mut self, value: T) -> Result<(), T>
pub fn push(&mut self, value: T) -> Result<(), T>
Tries to push a new item by moving or copying it.
This method must not be used to push items after a ConsIter::pop.
In this case, Self::push_init has to be used, instead.
For more info, refer to the main documentation above.
Returns:
Err(value), if the buffer is full;Ok(()), otherwise.
Sourcepub fn push_init(&mut self, value: T) -> Result<(), T>
pub fn push_init(&mut self, value: T) -> Result<(), T>
Same as Self::push_slice, but can be used when dealing with possibly uninitialised
locations within the buffer, e.g. after a ConsIter::pop.
Returns:
Err(value), if the buffer is full;Ok(()), otherwise.
Sourcepub fn push_slice(&mut self, slice: &[T]) -> Option<()>where
T: Copy,
pub fn push_slice(&mut self, slice: &[T]) -> Option<()>where
T: Copy,
Tries to push a slice of items by copying the elements.
The elements must implement Copy trait.
This method must not be used to push items after a ConsIter::pop.
In this case, Self::push_slice_init has to be used, instead.
For more info, refer to the main documentation above.
Returns:
None, if the buffer is full;Some(()), otherwise.
Sourcepub fn push_slice_init(&mut self, slice: &[T]) -> Option<()>where
T: Copy,
pub fn push_slice_init(&mut self, slice: &[T]) -> Option<()>where
T: Copy,
Same as Self::push_slice, but can be used when dealing with possibly uninitialised
locations within the buffer, e.g. after a ConsIter::pop.
Returns:
None, if the buffer is full;Some(()), otherwise.
Sourcepub fn push_slice_clone(&mut self, slice: &[T]) -> Option<()>where
T: Clone,
pub fn push_slice_clone(&mut self, slice: &[T]) -> Option<()>where
T: Clone,
Tries to push a slice of items by cloning the elements.
The elements must implement Clone trait.
This method must not be used to push items after a ConsIter::pop.
In this case, Self::push_slice_clone_init has to be used, instead.
For more info, refer to the main documentation above.
Returns:
None, if the buffer is full;Some(()), otherwise.
Sourcepub fn push_slice_clone_init(&mut self, slice: &[T]) -> Option<()>where
T: Clone,
pub fn push_slice_clone_init(&mut self, slice: &[T]) -> Option<()>where
T: Clone,
Same as Self::push_slice_clone, but can be used when dealing with possibly uninitialised
locations within the buffer, e.g. after a ConsIter::pop.
Returns:
None, if the buffer is full;Some(()), otherwise.
Sourcepub unsafe fn get_next_item_mut<'a>(&mut self) -> Option<&'a mut T>
pub unsafe fn get_next_item_mut<'a>(&mut self) -> Option<&'a mut T>
If available, returns a mutable reference to the next item. This reference can be used to write data into an initialised item.
Items can be initialised by calling Self::get_next_item_mut_init or by creating a buffer
using default constructor. E.g.: ConcurrentHeapRB::default or LocalStackRB::default.
For uninitialised items, use Self::get_next_item_mut_init, instead.
Being this a reference, Self::advance has to be called when done with the mutation
in order to move the iterator.
§Safety
The retrieved item must be initialised! For more info, refer to MaybeUninit::assume_init_mut.
Sourcepub fn get_next_item_mut_init(&mut self) -> Option<*mut T>
pub fn get_next_item_mut_init(&mut self) -> Option<*mut T>
If available, returns a mutable pointer to the next item. This pointer can be used to write data into the item, even if this is not already initialised. It is important to note that reading from this pointer or turning it into a reference is still undefined behavior, unless the item is initialized.
If the memory pointed by this pointer is already initialised, it is possible to write into it with a simple:
*ptr = value;Doing so, the old value will be automatically dropped and no leak will be created.
If the memory is not initialised, the write must be done with:
ptr.write(value);The reason is that write does not drop the old value, which is good, because dropping an
uninitialised value is UB!
One should be able to test whether a piece of memory is initialised with UnsafeSyncCell::check_zeroed.
For more info, refer to MaybeUninit::as_mut_ptr.
Being this a pointer, Self::advance has to be called when done with the mutation
in order to move the iterator.
Sourcepub unsafe fn get_next_slices_mut<'a>(
&mut self,
count: usize,
) -> Option<MutableSlice<'a, T>>
pub unsafe fn get_next_slices_mut<'a>( &mut self, count: usize, ) -> Option<MutableSlice<'a, T>>
If available, returns two mutable slices with a total count equal to count.
These references can be used to write data into initialised items.
Items can be initialised (one by one) by calling Self::get_next_item_mut_init or by creating a buffer
using default constructor. E.g.: ConcurrentHeapRB::default or LocalStackRB::default.
Being these reference, Self::advance has to be called when done with the mutation
in order to move the iterator.
§Safety
The retrieved items must be initialised! For more info, refer to MaybeUninit::assume_init_mut.
Trait Implementations§
Source§impl<B: MutRB<Item = T>, T> MRBIterator for ProdIter<'_, B>
impl<B: MutRB<Item = T>, T> MRBIterator for ProdIter<'_, B>
type Item = T
Source§fn detach(self) -> Detached<Self>where
Self: Sized,
fn detach(self) -> Detached<Self>where
Self: Sized,
Detached.Source§fn wait_for(&mut self, count: usize)
fn wait_for(&mut self, count: usize)
count available items.Source§fn alive_iters(&self) -> u8
fn alive_iters(&self) -> u8
Source§fn prod_index(&self) -> usize
fn prod_index(&self) -> usize
Source§fn work_index(&self) -> usize
fn work_index(&self) -> usize
Source§fn cons_index(&self) -> usize
fn cons_index(&self) -> usize
Source§fn get_workable<'a>(&mut self) -> Option<&'a mut Self::Item>
fn get_workable<'a>(&mut self) -> Option<&'a mut Self::Item>
Source§fn get_workable_slice_exact<'a>(
&mut self,
count: usize,
) -> Option<MutableSlice<'a, <Self as MRBIterator>::Item>>
fn get_workable_slice_exact<'a>( &mut self, count: usize, ) -> Option<MutableSlice<'a, <Self as MRBIterator>::Item>>
count. Read moreSource§fn get_workable_slice_avail<'a>(
&mut self,
) -> Option<MutableSlice<'a, <Self as MRBIterator>::Item>>
fn get_workable_slice_avail<'a>( &mut self, ) -> Option<MutableSlice<'a, <Self as MRBIterator>::Item>>
Self::available(). Read moreSource§fn get_workable_slice_multiple_of<'a>(
&mut self,
rhs: usize,
) -> Option<MutableSlice<'a, <Self as MRBIterator>::Item>>
fn get_workable_slice_multiple_of<'a>( &mut self, rhs: usize, ) -> Option<MutableSlice<'a, <Self as MRBIterator>::Item>>
rhs. Read more