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
121
122
123
124
125
126
127
128
129
130
131
132
//! # Parallel Worker
//!
//! This crate 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 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. 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::*;
//!
//! # 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_blocking(), Some(1));
//! assert_eq!(worker.get_vec_blocking(), (2..=10).collect::<Vec<_>>());
//! }
//! ```
pub use State;
pub use ;
pub use ;