1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
//! # Parallel Worker
//!
//! This crate provides a simple interface for running tasks in parallel.
//! The Worker structs are used to dispatch tasks to worker threads and collect the results.
//! You can wait for results or receive 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 cancellation 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 mut 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. Excessive checking will lead to a performance costs.
//! Canceled tasks will stop executing as soon as they reach a [`check_if_cancelled!`].
//! Results of canceled tasks will be discarded.
//! Results of tasks that have already completed will remain unaffected.
//! ```rust
//! use parallel_worker::prelude::*;
//!
//! # use std::{thread::sleep, time::Duration};
//! fn main() {
//! let mut 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 mut 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::*;
//! # use std::{thread::sleep, time::Duration};
//!
//! fn main() {
//! let mut 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_vec_blocking(), (1..=10).collect::<Vec<_>>());
//! }
//! ```
pub use State;
pub use ;
pub use ;