pub struct FillQueue<T, A: Allocator = Global> { /* private fields */ }
alloc
only.Expand description
An atomic queue intended for use cases where taking the full contents of the queue is needed.
The queue is, basically, an atomic singly-linked list, where nodes are first allocated and then the list’s tail is atomically updated.
When the queue is “chopped”, the list’s tail is swaped to null, and it’s previous tail is used as the base of the ChopIter
§Performance
The performance of pushing elements is expected to be similar to pushing elements to a SegQueue
or Mutex<Vec<_>>
,
but “chopping” elements is expected to be arround 2 times faster than with a Mutex<Vec<_>>
, and 3 times faster than a SegQueue
You can see the benchmark results here
§Use FillQueue
when:
- You want a queue that’s updateable by shared reference
- You want to retreive all elements of the queue at once
- There is no specifically desired order for the elements to be retreived on, or that order is LIFO (Last In First Out)
§Don’t use FillQueue
when:
- You don’t need a queue updateable by shared reference
- You want to retreive the elements of the queue one by one (see
SegQueue
) - You require the elements in a specific order that isn’t LIFO
Implementations§
Source§impl<T, A: Allocator> FillQueue<T, A>
impl<T, A: Allocator> FillQueue<T, A>
Source§impl<T, A: Allocator> FillQueue<T, A>
impl<T, A: Allocator> FillQueue<T, A>
Sourcepub fn try_push(&self, v: T) -> Result<(), AllocError>
pub fn try_push(&self, v: T) -> Result<(), AllocError>
Uses atomic operations to push an element to the queue.
§Errors
This method returns an error if alloc
fails to allocate the memory needed for the node.
§Example
use utils_atomics::prelude::*;
let queue = FillQueue::<i32>::new();
assert!(queue.try_push(1).is_ok());
assert_eq!(queue.chop().next(), Some(1));
Sourcepub fn try_push_mut(&mut self, v: T) -> Result<(), AllocError>
pub fn try_push_mut(&mut self, v: T) -> Result<(), AllocError>
Uses non-atomic operations to push an element to the queue.
§Safety
This method is safe because the mutable reference guarantees we are the only thread that can access this queue.
§Errors
This method returns an error if alloc
fails to allocate the memory needed for the node.
§Example
use utils_atomics::prelude::*;
let mut queue = FillQueue::<i32>::new();
assert!(queue.try_push_mut(1).is_ok());
assert_eq!(queue.chop_mut().next(), Some(1));
Source§impl<T, A: Allocator> FillQueue<T, A>
impl<T, A: Allocator> FillQueue<T, A>
Sourcepub fn chop(&self) -> ChopIter<T, A> ⓘwhere
A: Clone,
pub fn chop(&self) -> ChopIter<T, A> ⓘwhere
A: Clone,
Returns a LIFO (Last In First Out) iterator over a chopped chunk of a FillQueue
.
The elements that find themselves inside the chopped region of the queue will be accessed through non-atomic operations.
§Example
use utils_atomics::prelude::*;
let queue = FillQueue::<i32>::new();
queue.push(1);
queue.push(2);
queue.push(3);
let mut iter = queue.chop();
assert_eq!(iter.next(), Some(3));
assert_eq!(iter.next(), Some(2));
assert_eq!(iter.next(), Some(1));
assert_eq!(iter.next(), None)
Sourcepub fn chop_mut(&mut self) -> ChopIter<T, A> ⓘwhere
A: Clone,
pub fn chop_mut(&mut self) -> ChopIter<T, A> ⓘwhere
A: Clone,
Returns a LIFO (Last In First Out) iterator over a chopped chunk of a FillQueue
. The chopping is done with non-atomic operations.
§Safety
This method is safe because the mutable reference guarantees we are the only thread that can access this queue.
§Example
use utils_atomics::prelude::*;
let mut queue = FillQueue::<i32>::new();
queue.push_mut(1);
queue.push_mut(2);
queue.push_mut(3);
let mut iter = queue.chop_mut();
assert_eq!(iter.next(), Some(3));
assert_eq!(iter.next(), Some(2));
assert_eq!(iter.next(), Some(1));
assert_eq!(iter.next(), None)