pub struct ProcessPool<T: Task> { /* private fields */ }Expand description
A pool of worker processes for concurrent task execution.
ProcessPool manages multiple worker processes, distributing tasks across them
using round-robin scheduling. Each worker runs in its own isolated process with
automatic crash recovery.
§Example
use std::num::NonZeroUsize;
use tarnish::{Task, ProcessPool};
#[derive(Default)]
struct HeavyComputation;
impl Task for HeavyComputation {
type Input = Vec<u8>;
type Output = u64;
type Error = String;
fn run(&mut self, input: Vec<u8>) -> Result<u64, String> {
// Expensive computation here
Ok(input.iter().map(|&x| x as u64).sum())
}
}
tarnish::main::<HeavyComputation>(|| {
let size = NonZeroUsize::new(4).unwrap();
let mut pool = ProcessPool::<HeavyComputation>::new(size)
.expect("Failed to create pool");
// Process 100 items across 4 workers
for i in 0..100 {
let result = pool.call(vec![i; 1000]);
println!("Result {}: {:?}", i, result);
}
});Implementations§
Source§impl<T: Task> ProcessPool<T>
impl<T: Task> ProcessPool<T>
Sourcepub fn new(size: NonZeroUsize) -> Result<Self>
pub fn new(size: NonZeroUsize) -> Result<Self>
Create a new process pool with the specified number of workers.
Each worker is a separate process that will be spawned immediately. If any worker fails to spawn, an error is returned and no pool is created.
§Arguments
size- The number of worker processes to spawn (must be non-zero).
§Errors
Returns an error if any worker process fails to spawn.
§Example
use std::num::NonZeroUsize;
use tarnish::ProcessPool;
let size = NonZeroUsize::new(4).unwrap();
let pool = ProcessPool::<MyTask>::new(size)?;Examples found in repository?
34fn main() {
35 tarnish::main::<HeavyComputation>(|| {
36 eprintln!("Creating pool with 4 workers...");
37
38 let size = NonZeroUsize::new(4).unwrap();
39 let mut pool = match ProcessPool::<HeavyComputation>::new(size) {
40 Ok(p) => p,
41 Err(e) => {
42 eprintln!("Failed to create pool: {e}");
43 return;
44 }
45 };
46
47 let pool_size = pool.size();
48 eprintln!("Pool size: {pool_size}\n");
49
50 // Process 12 tasks across 4 workers
51 // Each worker should get ~3 tasks due to round-robin
52 eprintln!("Processing 12 tasks across {pool_size} workers:\n");
53
54 for i in 1_usize..=12 {
55 eprintln!("[Parent] Submitting task {i}");
56
57 // Use saturating_mul to avoid arithmetic overflow
58 let input = i.saturating_mul(100);
59
60 match pool.call(input) {
61 Ok(result) => eprintln!("[Parent] Task {i} result: {result}\n"),
62 Err(e) => eprintln!("[Parent] Task {i} failed: {e}\n"),
63 }
64 }
65
66 eprintln!("All tasks completed!");
67 });
68}Sourcepub fn call(&mut self, input: T::Input) -> Result<T::Output>
pub fn call(&mut self, input: T::Input) -> Result<T::Output>
Execute a task on the next available worker.
This method uses round-robin scheduling to distribute work across workers. The call blocks until the worker returns a result. If the worker crashes, it will be automatically restarted.
§Errors
Returns an error if:
- The worker process crashes and cannot be restarted
- Communication with the worker fails
- The worker returns a task error
§Example
let size = NonZeroUsize::new(4).unwrap();
let mut pool = ProcessPool::<MyTask>::new(size)?;
let result = pool.call("hello".to_string())?;Examples found in repository?
34fn main() {
35 tarnish::main::<HeavyComputation>(|| {
36 eprintln!("Creating pool with 4 workers...");
37
38 let size = NonZeroUsize::new(4).unwrap();
39 let mut pool = match ProcessPool::<HeavyComputation>::new(size) {
40 Ok(p) => p,
41 Err(e) => {
42 eprintln!("Failed to create pool: {e}");
43 return;
44 }
45 };
46
47 let pool_size = pool.size();
48 eprintln!("Pool size: {pool_size}\n");
49
50 // Process 12 tasks across 4 workers
51 // Each worker should get ~3 tasks due to round-robin
52 eprintln!("Processing 12 tasks across {pool_size} workers:\n");
53
54 for i in 1_usize..=12 {
55 eprintln!("[Parent] Submitting task {i}");
56
57 // Use saturating_mul to avoid arithmetic overflow
58 let input = i.saturating_mul(100);
59
60 match pool.call(input) {
61 Ok(result) => eprintln!("[Parent] Task {i} result: {result}\n"),
62 Err(e) => eprintln!("[Parent] Task {i} failed: {e}\n"),
63 }
64 }
65
66 eprintln!("All tasks completed!");
67 });
68}Sourcepub const fn size(&self) -> usize
pub const fn size(&self) -> usize
Returns the number of workers in the pool.
§Example
let size = NonZeroUsize::new(4).unwrap();
let pool = ProcessPool::<MyTask>::new(size)?;
assert_eq!(pool.size(), 4);Examples found in repository?
34fn main() {
35 tarnish::main::<HeavyComputation>(|| {
36 eprintln!("Creating pool with 4 workers...");
37
38 let size = NonZeroUsize::new(4).unwrap();
39 let mut pool = match ProcessPool::<HeavyComputation>::new(size) {
40 Ok(p) => p,
41 Err(e) => {
42 eprintln!("Failed to create pool: {e}");
43 return;
44 }
45 };
46
47 let pool_size = pool.size();
48 eprintln!("Pool size: {pool_size}\n");
49
50 // Process 12 tasks across 4 workers
51 // Each worker should get ~3 tasks due to round-robin
52 eprintln!("Processing 12 tasks across {pool_size} workers:\n");
53
54 for i in 1_usize..=12 {
55 eprintln!("[Parent] Submitting task {i}");
56
57 // Use saturating_mul to avoid arithmetic overflow
58 let input = i.saturating_mul(100);
59
60 match pool.call(input) {
61 Ok(result) => eprintln!("[Parent] Task {i} result: {result}\n"),
62 Err(e) => eprintln!("[Parent] Task {i} failed: {e}\n"),
63 }
64 }
65
66 eprintln!("All tasks completed!");
67 });
68}