thread_tree

Struct ThreadTree

Source
pub struct ThreadTree { /* private fields */ }
Expand description

A hierarchical thread pool used for splitting work in a branching fashion.

See ThreadTree::new_with_level() to create a new thread tree, and see ThreadTree::top() for a usage example.

The thread tree has the benefit that at each level, jobs can be sent directly to the thread that is going to execute it - that means there is no contention between waiting threads. The downside is that the structure of the thread tree is rather static.

Implementations§

Source§

impl ThreadTree

Source

pub const fn new_level0() -> Self

Create a level 0 tree (with no parallelism)

Source

pub fn new_with_level(level: usize) -> Box<Self>

Create an n-level thread tree with 2n leaves

Level 0 has no parallelism Level 1 has two nodes Level 2 has four nodes (et.c.)

Level must be <= 12; panics on invalid input

Source

pub fn is_parallel(&self) -> bool

Return true if this is a non-dummy pool which will parallelize in join

Source

pub fn top(&self) -> ThreadTreeCtx<'_>

Get the top thread tree context, where we can inject tasks with join. Each job gets a sub-context that can be used to inject tasks further down the corresponding branch of the tree.

Note to avoid deadlocks, tasks should never be injected into a tree context that doesn’t belong to the current level. To avoid this should be easy - only call .top() at the top level.

The following example shows using a two-level tree and using context to spawn tasks.

use thread_tree::{ThreadTree, ThreadTreeCtx};

let tp = ThreadTree::new_with_level(2);

fn f(index: i32, ctx: ThreadTreeCtx<'_>) -> i32 {
    // do work in subtasks here
    let (a, b) = ctx.join(move |_| index + 1, |_| index + 2);

    return a + b;
}

let (r0, r1) = tp.top().join(|ctx| f(0, ctx), |ctx| f(1, ctx));

assert_eq!(r0 + r1, (0 + 1) + (0 + 2) + (1 + 1) + (1 + 2));

Trait Implementations§

Source§

impl Debug for ThreadTree

Source§

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

Formats the value using the given formatter. Read more

Auto Trait Implementations§

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