ThreadPool

Struct ThreadPool 

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

Thread Pool

A thread pool coordinates a group of threads to run taks in parallel.

§Example

use job_pool::ThreadPool;

let pool = ThreadPool::with_size(32).expect("Error creating pool");
pool.execute(|| println!("Hello world!"));

Implementations§

Source§

impl ThreadPool

Source

pub fn new(config: PoolConfig) -> Result<ThreadPool>

Creates a new ThreadPool

§Errors

If the PoolConfig is not valid

Examples found in repository?
examples/scopes.rs (line 10)
8pub fn main() {
9    let conf = PoolConfig::builder().max_jobs(16).build();
10    let pool = ThreadPool::new(conf).unwrap();
11
12    let nums = (0..1000).collect::<Vec<_>>();
13
14    let n = Mutex::new(0);
15
16    fn delay() {
17        use core::hash::BuildHasher;
18        let rand = RandomState::new().build_hasher().finish();
19        let millis = rand % 500;
20        std::thread::sleep(Duration::from_millis(1000 + millis));
21    }
22
23    pool.scope(|scope| {
24        scope.subscope(|sc| {
25            sc.execute(|| {
26                delay();
27                *n.lock().unwrap() += nums.iter().sum::<usize>();
28                println!("Sum1");
29            });
30            sc.execute(|| {
31                delay();
32                *n.lock().unwrap() += nums.iter().filter(|n| *n % 2 == 0).sum::<usize>();
33                println!("Sum even");
34            });
35        });
36
37        scope.subscope(|sc| {
38            sc.execute(|| {
39                delay();
40                *n.lock().unwrap() *= nums.iter().max().unwrap();
41                println!("Mul max");
42            });
43
44            sc.execute(|| {
45                delay();
46                *n.lock().unwrap() *= nums[nums.len() / 2];
47                println!("Mul mid");
48            });
49        });
50    });
51
52    let mut expected = 0;
53    expected += nums.iter().sum::<usize>();
54    expected += nums.iter().filter(|n| *n % 2 == 0).sum::<usize>();
55    expected *= nums.iter().max().unwrap();
56    expected *= nums[nums.len() / 2];
57
58    let n = *n.lock().unwrap();
59    assert_eq!(n, expected);
60    println!("{n} == {expected}");
61}
Source

pub fn with_default_config() -> Self

Create a ThreadPool with the default configuration

Source

pub fn with_size(size: u16) -> Result<Self>

Create a ThreadPool with a given size

Examples found in repository?
examples/example.rs (line 6)
4pub fn main() {
5    const N: i16 = 1024;
6    let pool = ThreadPool::with_size(32).expect("Expected Ok value");
7    let count = Arc::new(Mutex::new(0));
8
9    let inc = |i: i16| {
10        for _ in 0..N {
11            let count = Arc::clone(&count);
12            pool.execute(move || {
13                let mut n = count.lock().unwrap();
14                *n += i;
15            })
16        }
17    };
18
19    let check = |i: i16| {
20        let n = count.lock().unwrap();
21        assert_eq!(*n,i);
22    };
23
24    inc(1);
25    pool.join();
26    check(N);
27
28    inc(-1);
29    pool.join();
30    check(0);
31}
Source

pub fn pending_jobs(&self) -> usize

Returns the number of pending jobs

Source

pub fn execute(&self, job: impl Job<'static>)

Executes the given job inside this pool.

§Example
use job_pool::ThreadPool;

fn heavy_computation(n: u64) -> u64 {
    // ....
    n
}

let pool = ThreadPool::default();
pool.execute(|| {
    println!("JOB1: {}", heavy_computation(1));
});

pool.execute(|| {
    println!("JOB2: {}", heavy_computation(2));
});
Examples found in repository?
examples/example.rs (lines 12-15)
4pub fn main() {
5    const N: i16 = 1024;
6    let pool = ThreadPool::with_size(32).expect("Expected Ok value");
7    let count = Arc::new(Mutex::new(0));
8
9    let inc = |i: i16| {
10        for _ in 0..N {
11            let count = Arc::clone(&count);
12            pool.execute(move || {
13                let mut n = count.lock().unwrap();
14                *n += i;
15            })
16        }
17    };
18
19    let check = |i: i16| {
20        let n = count.lock().unwrap();
21        assert_eq!(*n,i);
22    };
23
24    inc(1);
25    pool.join();
26    check(N);
27
28    inc(-1);
29    pool.join();
30    check(0);
31}
Source

pub fn scope<'scope, 'pool, F, R>(&'pool self, f: F) -> R
where F: FnOnce(&Scope<'scope, 'pool>) -> R, 'pool: 'scope,

Creates a new Scope to spawn jobs.

All the jobs spawned via Scope::execute, will be joined when the scope drops.

§Example
use job_pool::ThreadPool;

let pool = ThreadPool::default();

let msg = String::from("Helloo :)");
pool.scope(|scope| {
    scope.execute(|| {
        println!("I'm job1, borrowing {msg:?}");
    });
    scope.execute(|| {
        println!("I'm job2, borrowing {msg:?}");
    });
});

// At this point, all the jobs spawned inside the scope above
// are done. That's wy it is ok to borrow msg, because we make
// sure that the jobs don't outlive the scope's lifetime.
Examples found in repository?
examples/scopes.rs (lines 23-50)
8pub fn main() {
9    let conf = PoolConfig::builder().max_jobs(16).build();
10    let pool = ThreadPool::new(conf).unwrap();
11
12    let nums = (0..1000).collect::<Vec<_>>();
13
14    let n = Mutex::new(0);
15
16    fn delay() {
17        use core::hash::BuildHasher;
18        let rand = RandomState::new().build_hasher().finish();
19        let millis = rand % 500;
20        std::thread::sleep(Duration::from_millis(1000 + millis));
21    }
22
23    pool.scope(|scope| {
24        scope.subscope(|sc| {
25            sc.execute(|| {
26                delay();
27                *n.lock().unwrap() += nums.iter().sum::<usize>();
28                println!("Sum1");
29            });
30            sc.execute(|| {
31                delay();
32                *n.lock().unwrap() += nums.iter().filter(|n| *n % 2 == 0).sum::<usize>();
33                println!("Sum even");
34            });
35        });
36
37        scope.subscope(|sc| {
38            sc.execute(|| {
39                delay();
40                *n.lock().unwrap() *= nums.iter().max().unwrap();
41                println!("Mul max");
42            });
43
44            sc.execute(|| {
45                delay();
46                *n.lock().unwrap() *= nums[nums.len() / 2];
47                println!("Mul mid");
48            });
49        });
50    });
51
52    let mut expected = 0;
53    expected += nums.iter().sum::<usize>();
54    expected += nums.iter().filter(|n| *n % 2 == 0).sum::<usize>();
55    expected *= nums.iter().max().unwrap();
56    expected *= nums[nums.len() / 2];
57
58    let n = *n.lock().unwrap();
59    assert_eq!(n, expected);
60    println!("{n} == {expected}");
61}
Source

pub fn join(&self)

Waits for all the jobs in the pool to finish

Examples found in repository?
examples/example.rs (line 25)
4pub fn main() {
5    const N: i16 = 1024;
6    let pool = ThreadPool::with_size(32).expect("Expected Ok value");
7    let count = Arc::new(Mutex::new(0));
8
9    let inc = |i: i16| {
10        for _ in 0..N {
11            let count = Arc::clone(&count);
12            pool.execute(move || {
13                let mut n = count.lock().unwrap();
14                *n += i;
15            })
16        }
17    };
18
19    let check = |i: i16| {
20        let n = count.lock().unwrap();
21        assert_eq!(*n,i);
22    };
23
24    inc(1);
25    pool.join();
26    check(N);
27
28    inc(-1);
29    pool.join();
30    check(0);
31}

Trait Implementations§

Source§

impl Default for ThreadPool

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl Drop for ThreadPool

Source§

fn drop(&mut self)

Executes the destructor for this 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> 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.