Struct FillQueue

Source
pub struct FillQueue<T, A: Allocator = Global> { /* private fields */ }
Available on crate feature 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> FillQueue<T>

Source

pub const fn new() -> Self

Creates a new FillQueue with the global allocator.

§Example
use utils_atomics::prelude::*;

let queue = FillQueue::<i32>::new();
Source§

impl<T, A: Allocator> FillQueue<T, A>

Source

pub const fn new_in(alloc: A) -> Self

Available on crate feature alloc_api only.

Creates a new FillQueue with the given allocator.

§Example
#![feature(allocator_api)]

use utils_atomics::prelude::*;
use std::alloc::Global;

let queue = FillQueue::<i32>::new_in(Global);
Source

pub fn allocator(&self) -> &A

Available on crate feature alloc_api only.

Returns a reference to this queue’s allocator.

§Example
#![feature(allocator_api)]

use utils_atomics::prelude::*;
use std::alloc::Global;

let queue = FillQueue::<i32>::new();
let alloc : &Global = queue.allocator();
Source§

impl<T, A: Allocator> FillQueue<T, A>

Source

pub fn is_empty(&self) -> bool

Returns true if the que is currently empty, false otherwise.

§Safety

Whilst this method is not unsafe, it’s result should be considered immediately stale.

§Example
use utils_atomics::prelude::*;

let queue = FillQueue::<i32>::new();
assert!(queue.is_empty());
Source

pub fn push(&self, v: T)

Uses atomic operations to push an element to the queue.

§Panics

This method panics if alloc fails to allocate the memory needed for the node.

§Example
use utils_atomics::prelude::*;

let queue = FillQueue::<i32>::new();
queue.push(1);
assert_eq!(queue.chop().next(), Some(1));
Source

pub fn push_mut(&mut self, v: T)

Uses non-atomic operations to push an element to the queue.

§Panics

This method panics if alloc fails to allocate the memory needed for the node.

§Example
use utils_atomics::prelude::*;

let mut queue = FillQueue::<i32>::new();
queue.push_mut(1);
assert_eq!(queue.chop_mut().next(), Some(1));
Source

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));
Source

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>

Source

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)
Source

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)

Trait Implementations§

Source§

impl<T, A: Debug + Allocator> Debug for FillQueue<T, A>

Source§

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

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

impl<T: Send, A: Send + Allocator> Send for FillQueue<T, A>

Source§

impl<T: Sync, A: Sync + Allocator> Sync for FillQueue<T, A>

Auto Trait Implementations§

§

impl<T, A = Global> !Freeze for FillQueue<T, A>

§

impl<T, A> RefUnwindSafe for FillQueue<T, A>
where A: RefUnwindSafe,

§

impl<T, A> Unpin for FillQueue<T, A>
where A: Unpin,

§

impl<T, A> UnwindSafe for FillQueue<T, A>

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> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

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

Source§

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>,

Source§

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.