[][src]Struct voluntary_servitude::VoluntaryServitude

pub struct VoluntaryServitude<T>(_);

Appendable list with lock-free iterator (also called VS)

Examples

Single thread

let (a, b, c) = (0usize, 1usize, 2usize);
// VS alias to VoluntaryServitude
// vs! alias to voluntary_servitude! (and operates like vec!)
let list = vs![a, b, c];
assert_eq!(list.iter().collect::<Vec<_>>(), vec![&a, &b, &c]);

// Current VS's length
// Be careful with race conditions since the value, when used, may not be true anymore
assert_eq!(list.len(), 3);

// The 'iter' method makes a lock-free iterator (Iter)
for (index, element) in list.iter().enumerate() {
    assert_eq!(index, *element);
}

// You can get the current iteration index
// iter.index() == iter.len() means iteration ended (iter.next() == None)
let mut iter = &mut list.iter();
assert_eq!(iter.index(), 0);
assert_eq!(iter.next(), Some(&0));
assert_eq!(iter.index(), 1);

// List can also be cleared (but current iterators are not affected)
list.clear();

assert_eq!(iter.len(), 3);
assert_eq!(list.len(), 0);
assert_eq!(list.iter().len(), 0);
assert_eq!((&mut list.iter()).next(), None);

println!("Single thread example ended without errors");

Multi-producer, multi-consumer

use std::{sync::Arc, thread::spawn};

const CONSUMERS: usize = 8;
const PRODUCERS: usize = 4;
const ELEMENTS: usize = 10_000_000;

fn main() {
    let list = Arc::new(vs![]);
    let mut handlers = vec![];

    // Creates producer threads to insert 10k elements
    for _ in 0..PRODUCERS {
        let l = Arc::clone(&list);
        handlers.push(spawn(move || {
            let _ = (0..ELEMENTS).map(|i| l.append(i)).count();
        }));
    }

    // Creates consumer threads to print number of elements
    // Until all of them are inserted
    for _ in 0..CONSUMERS {
        const TOTAL: usize = PRODUCERS * ELEMENTS;
        let consumer = Arc::clone(&list);
        handlers.push(spawn(move || loop {
            let count = consumer.iter().count();
            println!("{} elements", count);
            if count >= TOTAL { break };
        }));
    }

    // Join threads
    for handler in handlers.into_iter() {
        handler.join().expect("Failed to join thread");
    }

    println!("Multi-thread example ended without errors");
}

Methods

impl<T: Send + Sync> VoluntaryServitude<T>[src]

pub fn par_extend<I>(&self, par_iter: I) where
    I: IntoParallelIterator<Item = T>, 
[src]

This is supported on feature="rayon-traits" only.

Parallely Extends VS like the ParallelExtend trait, but without a mutable reference

let list = vs![1, 2, 3];
list.par_extend(vec![4, 5, 6]);
assert_eq!(list.iter().sum::<i32>(), 21);

impl<T> VoluntaryServitude<T>[src]

pub fn new() -> Self[src]

Creates new empty VS (like Default trait)

let list: VS<()> = VS::new();
assert!(list.is_empty());

pub fn append(&self, value: T)[src]

Inserts element after last node

let list = vs![];
let mut iter = list.iter();

list.append(3);
// Iter doesn't grow if it's empty (originally empty or was consumed)
assert!(iter.is_empty());

iter = list.iter();
list.append(8);
// Iter grows if it has not been consumed
assert_eq!(iter.collect::<Vec<_>>(), vec![&3, &8]);

Important traits for &'a mut Iter<T>
pub fn iter(&self) -> Iter<T>[src]

Makes lock-free iterator based on VS

let list = vs![3, 2];
assert_eq!(list.iter().collect::<Vec<_>>(), vec![&3, &2]);

for (element, expected) in list.iter().zip(&[3, 2][..]) {
    assert_eq!(element, expected);
}

pub fn len(&self) -> usize[src]

Returns current size, be careful with race conditions when using it since other threads can change it right after the read

Relaxed ordering is used to extract the length, so you shouldn't depend on this being sequentially consistent, only atomic

let list = vs![3, 2];
assert_eq!(list.len(), 2);
list.append(5);
assert_eq!(list.len(), 3);
list.clear();
assert_eq!(list.len(), 0);

pub fn is_empty(&self) -> bool[src]

Checks if VS is currently empty, be careful with race conditions when using it since other threads can change it right after the read

Relaxed ordering is used to extract the length, so you shouldn't depend on this being sequentially consistent, only atomic

let list = vs![];
assert!(list.is_empty());
list.append(());
assert!(!list.is_empty());

pub fn clear(&self)[src]

Clears list (iterators referencing the old chain will still work)

let list = vs![3, 2];
let iter = list.iter();
list.clear();
assert_eq!(iter.len(), 2);
assert_eq!(list.len(), 0);
assert_eq!(list.iter().len(), 0);

Important traits for &'a mut Iter<T>
pub fn empty(&self) -> Iter<T>[src]

Clears list returning iterator to it (other iterators referencing the old chain will still work)

let list = vs![3, 2];
let iter = list.empty();
assert_eq!(iter.len(), 2);
assert_eq!(list.len(), 0);
assert_eq!(list.iter().len(), 0);

pub fn swap(&self, other: &Self)[src]

Swaps two VS

let list = vs![3, 2];
let list2 = vs![5, 4];
list.swap(&list2);
assert_eq!(list.iter().collect::<Vec<_>>(), vec![&5, &4]);
assert_eq!(list2.iter().collect::<Vec<_>>(), vec![&3, &2]);

pub fn extend<I: IntoIterator<Item = T>>(&self, iter: I)[src]

Extends VS like the Extend trait, but without a mutable reference

let list = vs![1, 2, 3];
list.extend(vec![4, 5, 6]);
assert_eq!(list.iter().collect::<Vec<_>>(), vec![&1, &2, &3, &4, &5, &6]);

// You can extend from another `VS` if you clone (or copy) each element
let list = vs![1, 2, 3];
list.extend(vs![4, 5, 6].iter().cloned());
assert_eq!(list.iter().collect::<Vec<_>>(), vec![&1, &2, &3, &4, &5, &6]);

Trait Implementations

impl<T> Default for VoluntaryServitude<T>[src]

impl<T> Extend<T> for VoluntaryServitude<T>[src]

impl<'a, T: 'a + Copy> Extend<&'a T> for VoluntaryServitude<T>[src]

impl<T: Debug> Debug for VoluntaryServitude<T>[src]

impl<T> FromIterator<T> for VoluntaryServitude<T>[src]

impl<'a, T: 'a + Copy> FromIterator<&'a T> for VoluntaryServitude<T>[src]

impl<T: Send + Sync> ParallelExtend<T> for VoluntaryServitude<T>[src]

impl<T: Send + Sync> FromParallelIterator<T> for VoluntaryServitude<T>[src]

impl<T: Serialize> Serialize for VoluntaryServitude<T>[src]

impl<'a, T: Deserialize<'a>> Deserialize<'a> for VoluntaryServitude<T>[src]

Auto Trait Implementations

impl<T> Send for VoluntaryServitude<T> where
    T: Send + Sync

impl<T> Sync for VoluntaryServitude<T> where
    T: Send + Sync

Blanket Implementations

impl<T, U> Into for T where
    U: From<T>, 
[src]

impl<T> From for T[src]

impl<T, U> TryFrom for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

impl<T> Borrow for T where
    T: ?Sized
[src]

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> BorrowMut for T where
    T: ?Sized
[src]

impl<T, U> TryInto for T where
    U: TryFrom<T>, 
[src]

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

The type returned in the event of a conversion error.

impl<T> DeserializeOwned for T where
    T: Deserialize<'de>, 
[src]

impl<T> Erased for T