parallel_worker 0.1.5

A parallel worker implementation in Rust. Allows to start tasks in parallel and receive the results blocking or non-blocking.
Documentation
# Parallel Worker


This [crate](https://crates.io/crates/parallel_worker) provides a simple interface for running tasks in parallel.
The `BasicWorker`, `CancelableWorker` or `OrderedWorker` structs are used to dispatch tasks to worker threads and collect the results. You can wait for results or recieve currently available results.

## Workers

There are three types of workers:
- `BasicWorker` is a simple worker that processes tasks in parallel using multiple worker threads.
- `CancelableWorker` has additional functionality for optional results and task cancelation during execution.
- `OrderedWorker` returns results in the same order as the tasks were added. 

## Example

Basic example of using a worker to run tasks in parallel using the `BasicWorker` struct.
Tasks start executing as soon as they are added. When all threads are busy, tasks are queued until a thread becomes available.
```rust
 use parallel_worker::prelude::*;

 fn main() {
    let worker = BasicWorker::new(|n| {
       // Answer to life, the universe and everything
       return 42;
    });
    worker.add_task(1);
    worker.add_task(2);
    assert_eq!(worker.get_blocking(), Some(42));
    
    worker.add_tasks(0..10);
    assert_eq!(worker.get_iter_blocking().count(), 11);
}
```
## Tasks can be canceled

If you want to cancel tasks during execution, use `CancelableWorker` and call the `check_if_cancelled!` 
macro in your worker function on a regular basis. Exessive checking will lead to a performance costs.
Canceled tasks will stop executing as soon as they reach a `check_if_cancelled!`, their results will be discarded.
Results of tasks that have already completed will remain unaffected.  
```rust
use parallel_worker::prelude::*;

fn main() {
    let worker = CancelableWorker::new(worker_function);
    worker.add_tasks([1, 2, 3, 4]);
    worker.cancel_tasks();
    assert!(worker.get_blocking().is_none());
}

fn worker_function(task: u64, state: &State) -> Option<u64> {
    loop {
        sleep(Duration::from_millis(50)); 
        check_if_cancelled!(state); 
    }
    unreachable!() 
}
```

## Results can be optional

If a worker returns [`None`] the result will be discarded. This feature is available in the [`CancelableWorker`].
 
```rust
use parallel_worker::prelude::*;

fn main() {
    let worker = CancelableWorker::new(|n: u64, _s: &State| {
        if n % 2 == 0 {
            Some(n)
        } else {
            None
        }
    });
    
    worker.add_tasks(1..=10);
    assert_eq!(worker.get_iter_blocking().count(), 5);
}
```

## Results can be ordered

If you want to get results in the same order as the tasks were added, use `OrderedWorker`.
```rust 
use parallel_worker::prelude::*;

fn main() {
    let worker = OrderedWorker::new(|n: u64| {
        sleep(std::time::Duration::from_millis(n % 3));
        n    
    });
    worker.add_task(1);
    worker.add_task(2);
    worker.add_tasks(3..=10);
    assert_eq!(worker.get_blocking(), Some(1));
    assert_eq!(worker.get_vec_blocking(), (2..=10).collect::<Vec<_>>());
}
```