parsli 0.0.2

Parallel status lines for Rust
Documentation
use std::borrow::BorrowMut;
use std::collections::{HashMap, VecDeque};
use std::fs::File;
use std::io::{Error, Write};
use std::sync::{Arc, RwLock};

use indicatif::{MultiProgress, ProgressDrawTarget};

use crate::graph::DependencyGraph;


/// The status of the pool
#[derive(Clone)]
pub enum Status {
    Idle, // The pool is not working.
    Busy(Option<Vec<String>>) // The pool is working. A subset of tasks can be specified.
}

pub type Task = fn(u64, u64) -> Result<(), String>;

/// A wrapper for showing progress of multiple dependent tasks
#[derive(Clone)]
pub struct Pool {
    /// Map of actions to execute
    tasks: Arc<RwLock<HashMap<String, Task>>>,
    /// Dependency graph
    graph: Arc<RwLock<DependencyGraph>>,
    /// Status bars and functions to pass them to
    queue: Arc<RwLock<VecDeque<Task>>>,
    /// Multi progress bar
    progress: Arc<MultiProgress>,
    /// Status
    status: Status,
}


impl Pool {
    /// Creates a new status display
    pub fn new() -> Self {
        Self {
            tasks: Default::default(),
            queue: Arc::new(RwLock::new(VecDeque::new())),
            /// High refresh rate progress bar
            progress: Arc::new(MultiProgress::with_draw_target(
                ProgressDrawTarget::stderr_with_hz(60),
            )),
            /// Empty graph
            graph: Arc::new(RwLock::new(DependencyGraph::new())),
            /// Do nothing initially
            status: Status::Idle,
        }
    }

    /// Add a new task
    pub fn add_task(&mut self, name: &str, task: Task, deps: Vec<&str>) {
        self.tasks.write().unwrap().insert(name.to_string(), task);
        for d in deps {
            self.graph.write().unwrap().push( name, d);
        }
    }

    /// Start the pool for a single task
    pub fn start_single(&mut self, name: &str) {
        self.start_multi(vec![name])
    }

    /// Start the pool for multiple tasks
    pub fn start_multi(&mut self, names: Vec<&str>) {
        self.status = Status::Busy(Some(names.iter().map(|s| s.to_string()).collect()));
    }

    /// Start all tasks
    pub fn start(&mut self) {
        self.status = Status::Busy(None);

        while let Some(name) = self.graph.write().unwrap().pop() {
            println!("{}", name);
        }
    }
}