1pub mod traits;
114
115pub use traits::{AsyncRunnable, ParallelRun, Runnable, Thread};
116
117#[cfg(feature = "tokio")]
118pub use traits::{TokioParallelRun, TokioTask};
119
120#[cfg(test)]
121mod tests {
122 use super::*;
123
124 struct TestTask(i32);
125 impl Runnable for TestTask {
126 type Output = i32;
127
128 fn run(self) -> Self::Output {
129 self.0 * 2
130 }
131 }
132
133 #[test]
134 fn it_works() {
135 let task = TestTask(10);
136 let handle = task.start();
137 assert_eq!(handle.join().unwrap(), 20);
138 }
139
140 #[test]
141 fn par_test() {
142 let tasks = (0..1_000_000).map(TestTask).collect::<Vec<_>>();
143
144 let results = tasks.par_run().unwrap();
145 assert_eq!(results, (0..1_000_000).map(|x| x * 2).collect::<Vec<_>>());
146 }
147
148 #[test]
149 fn par_test_empty() {
150 let results = Vec::<TestTask>::new().par_run().unwrap();
151 assert!(results.is_empty());
152 }
153
154 #[test]
155 fn test_builder() {
156 let task = TestTask(10);
157 let builder = std::thread::Builder::new().name("custom_thread".to_string());
158 let handle = task.start_with_builder(builder);
159 assert_eq!(handle.join().unwrap(), 20);
160
161 struct BuilderTask;
162
163 impl Runnable for BuilderTask {
164 type Output = String;
165
166 fn run(self) -> Self::Output {
167 std::thread::current().name().unwrap().to_string()
168 }
169 }
170
171 let builder = std::thread::Builder::new().name("custom_thread".to_string());
172 let handle = BuilderTask.start_with_builder(builder);
173 assert_eq!(handle.join().unwrap(), "custom_thread".to_string());
174 }
175
176 #[cfg(feature = "tokio")]
177 mod async_tests {
178 use super::*;
179
180 struct AsyncTestTask(i32);
181
182 impl AsyncRunnable for AsyncTestTask {
183 type Output = i32;
184
185 fn run(self) -> impl std::future::Future<Output = Self::Output> + Send {
186 async move {
187 tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;
188 self.0 * 2
189 }
190 }
191 }
192
193 #[tokio::test]
194 async fn test_async_task() {
195 let task = AsyncTestTask(21);
196 let handle = task.async_start();
197 assert_eq!(handle.await.unwrap(), 42);
198 }
199
200 #[tokio::test]
201 async fn test_async_parallel_run() {
202 let tasks = (0..10).map(AsyncTestTask).collect::<Vec<_>>();
203 let results = tasks.async_par_run().await.unwrap();
204 assert_eq!(results, (0..10).map(|x| x * 2).collect::<Vec<_>>());
205 }
206
207 #[tokio::test]
208 async fn test_async_parallel_run_empty() {
209 let tasks = Vec::<AsyncTestTask>::new();
210 let results = tasks.async_par_run().await.unwrap();
211 assert!(results.is_empty());
212 }
213
214 #[tokio::test]
215 async fn test_async_parallel_run_large() {
216 let tasks = (0..1_000).map(AsyncTestTask).collect::<Vec<_>>();
217 let results = tasks.async_par_run().await.unwrap();
218 assert_eq!(results, (0..1_000).map(|x| x * 2).collect::<Vec<_>>());
219 }
220
221 struct AsyncComplexTask {
222 value: i32,
223 multiplier: i32,
224 }
225
226 impl AsyncRunnable for AsyncComplexTask {
227 type Output = i32;
228
229 fn run(self) -> impl std::future::Future<Output = Self::Output> + Send {
230 async move {
231 tokio::time::sleep(tokio::time::Duration::from_millis(5)).await;
232 self.value * self.multiplier
233 }
234 }
235 }
236
237 #[tokio::test]
238 async fn test_async_complex_task() {
239 let task = AsyncComplexTask {
240 value: 7,
241 multiplier: 6,
242 };
243 let handle = task.async_start();
244 assert_eq!(handle.await.unwrap(), 42);
245 }
246
247 #[tokio::test]
248 async fn test_async_multiple_awaits() {
249 let task1 = AsyncTestTask(10);
250 let task2 = AsyncTestTask(20);
251 let task3 = AsyncTestTask(30);
252
253 let handle1 = task1.async_start();
254 let handle2 = task2.async_start();
255 let handle3 = task3.async_start();
256
257 let result1 = handle1.await.unwrap();
258 let result2 = handle2.await.unwrap();
259 let result3 = handle3.await.unwrap();
260
261 assert_eq!(result1, 20);
262 assert_eq!(result2, 40);
263 assert_eq!(result3, 60);
264 }
265
266 struct AsyncStringTask(String);
267
268 impl AsyncRunnable for AsyncStringTask {
269 type Output = String;
270
271 fn run(self) -> impl std::future::Future<Output = Self::Output> + Send {
272 async move {
273 tokio::time::sleep(tokio::time::Duration::from_millis(5)).await;
274 format!("Hello, {}!", self.0)
275 }
276 }
277 }
278
279 #[tokio::test]
280 async fn test_async_string_output() {
281 let task = AsyncStringTask("World".to_string());
282 let handle = task.async_start();
283 assert_eq!(handle.await.unwrap(), "Hello, World!");
284 }
285
286 #[tokio::test]
287 async fn test_async_parallel_run_strings() {
288 let tasks = vec![
289 AsyncStringTask("Alice".to_string()),
290 AsyncStringTask("Bob".to_string()),
291 AsyncStringTask("Charlie".to_string()),
292 ];
293 let results = tasks.async_par_run().await.unwrap();
294 assert_eq!(
295 results,
296 vec![
297 "Hello, Alice!".to_string(),
298 "Hello, Bob!".to_string(),
299 "Hello, Charlie!".to_string()
300 ]
301 );
302 }
303 }
304}