DispatchPool

Struct DispatchPool 

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

A specialized thread pool and queue for dispatching blocking (synchronous, long running) operations.

This pool is not an executor, has no waking facilities, etc. As compared with other thread pools supporting spawn, or spawn_blocking in tokio, here also called dispatch() or dispatch_rx() this pool has some unique features:

  • A configurable, fixed number of threads created before return from construction and terminated on Drop::drop. Consistent memory footprint. No warmup required. No per-task thread management overhead.

  • Configurable panic handling policy: Either catches and logs dispatch panics, or aborts the process, on panic unwind.

  • Supports fixed (bounded) or unbounded queue length.

  • When the queue is bounded and becomes full, DispatchPool::spawn pops the oldest operation off the queue before pushing the newest passed operation, to ensure space while holding a lock. Then as a fallback it runs the old operation. Thus we enlist calling threads once the queue reaches limit, but operation order (at least from perspective of a single thread) is preserved.

§Usage

By default, the pool uses an unbounded queue, with the assumption that resource/capacity is externally constrained. Once constructed, a fixed number of threads are spawned and the instance acts as a handle to the pool. This may be inexpensively cloned for additional handles to the same pool.

See DispatchPoolBuilder for an extensive set of options.

§With tokio’s threaded runtime

One can schedule a clone of the DispatchPool (handle) on each tokio runtime thread (tokio’s rt-threaded feature).

use blocking_permit::{
    DispatchPool, register_dispatch_pool, deregister_dispatch_pool
};

let pool = DispatchPool::builder().create();

let mut rt = tokio::runtime::Builder::new_multi_thread()
    .on_thread_start(move || {
        register_dispatch_pool(pool.clone());
    })
    .on_thread_stop(|| {
        deregister_dispatch_pool();
    })
    .build()
    .unwrap();

Implementations§

Source§

impl DispatchPool

Source

pub fn new() -> DispatchPool

Create new pool using defaults.

Source

pub fn builder() -> DispatchPoolBuilder

Create a new builder for configuring a new pool.

Source

pub fn spawn(&self, f: Box<dyn FnOnce() + Send>)

Enqueue a blocking operation to be executed.

This first attempts to send to the associated queue, which will always succeed if unbounded, e.g. no DispatchPoolBuilder::queue_length is set, the default. If however the queue is bounded and at capacity, then this task will be pushed after taking the oldest task, which is then run on the calling thread.

Trait Implementations§

Source§

impl Clone for DispatchPool

Source§

fn clone(&self) -> DispatchPool

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for DispatchPool

Source§

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

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

impl Default for DispatchPool

Source§

fn default() -> Self

Returns the “default value” for a type. 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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. 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> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. 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.