windjammer_runtime/platform/native/
compute.rs1use rayon::prelude::*;
3use std::thread;
4
5pub fn parallel<T, R, F>(items: Vec<T>, f: F) -> Vec<R>
7where
8 T: Send + Sync,
9 R: Send,
10 F: Fn(T) -> R + Send + Sync,
11{
12 items.into_par_iter().map(f).collect()
13}
14
15pub fn background<T, F>(f: F) -> BackgroundTask<T>
18where
19 T: Send + 'static,
20 F: FnOnce() -> T + Send + 'static,
21{
22 let handle = thread::spawn(f);
23 BackgroundTask {
24 handle: Some(handle),
25 }
26}
27
28pub fn num_workers() -> usize {
30 rayon::current_num_threads()
31}
32
33pub fn join<A, B, FA, FB>(a: FA, b: FB) -> (A, B)
35where
36 A: Send,
37 B: Send,
38 FA: FnOnce() -> A + Send,
39 FB: FnOnce() -> B + Send,
40{
41 rayon::join(a, b)
42}
43
44pub fn map_reduce<T, R, M, Red>(items: Vec<T>, map_fn: M, reduce_fn: Red, initial: R) -> R
46where
47 T: Send + Sync,
48 R: Send + Sync + Clone,
49 M: Fn(T) -> R + Send + Sync,
50 Red: Fn(R, R) -> R + Send + Sync,
51{
52 items
53 .into_par_iter()
54 .map(map_fn)
55 .reduce(|| initial.clone(), reduce_fn)
56}
57
58pub struct BackgroundTask<T> {
60 handle: Option<thread::JoinHandle<T>>,
61}
62
63impl<T> BackgroundTask<T> {
64 pub fn await_result(mut self) -> T {
66 self.handle
67 .take()
68 .expect("BackgroundTask already consumed")
69 .join()
70 .expect("Background task panicked")
71 }
72
73 pub fn is_ready(&self) -> bool {
75 self.handle
76 .as_ref()
77 .map(|h| h.is_finished())
78 .unwrap_or(true)
79 }
80}