use std::fmt::Write;
use std::sync::Arc;
use std::thread::{self, sleep};
use std::time::Duration;
use rand::Rng;
const THREAD_WORK_MAX: usize = 20;
struct JobState {
x: usize,
complete: bool,
}
struct Model {
job_state: Vec<JobState>,
}
impl nutmeg::Model for Model {
fn render(&mut self, _width: usize) -> String {
let mut s = String::new();
let n_jobs = self.job_state.len();
let n_complete = self.job_state.iter().filter(|j| j.complete).count();
writeln!(s, "{n_complete}/{n_jobs} complete").unwrap();
for (i, js) in self.job_state.iter().enumerate() {
let remains = THREAD_WORK_MAX - js.x;
writeln!(s, "{:3}: {}{}", i, "#".repeat(js.x), "_".repeat(remains)).unwrap();
}
s
}
}
fn work(i_thread: usize, arc_view: Arc<nutmeg::View<Model>>) {
let mut rng = rand::thread_rng();
for j in 0..=THREAD_WORK_MAX {
arc_view.update(|model| model.job_state[i_thread].x = j);
sleep(Duration::from_millis(rng.gen_range(100..600)));
}
arc_view.update(|model| model.job_state[i_thread].complete = true);
}
fn main() {
let model = Model {
job_state: Vec::new(),
};
let view = nutmeg::View::new(model, nutmeg::Options::default());
view.update(|_m| ());
let arc_view = Arc::new(view);
let mut join_handles = Vec::new();
for i_thread in 0..20 {
arc_view.update(|model| {
model.job_state.push(JobState {
x: 0,
complete: false,
})
});
sleep(Duration::from_millis(100));
let give_arc_view = arc_view.clone();
join_handles.push(thread::spawn(move || work(i_thread, give_arc_view)));
}
for join_handle in join_handles {
arc_view.update(|_m| ());
join_handle.join().unwrap();
}
arc_view.update(|_| ());
sleep(Duration::from_millis(500));
}