xmpd/src/process_manager.rs

79 lines
2.0 KiB
Rust

use std::{collections::HashMap, sync::{atomic::{AtomicUsize, Ordering}, Mutex, RwLock}};
use tokio::process::Command;
#[allow(dead_code)]
#[derive(Debug, Clone)]
struct Proc {
msg: String,
finished: bool
}
lazy_static::lazy_static!(
static ref PROCESSES: Mutex<RwLock<HashMap<usize, Proc>>> = Mutex::new(RwLock::new(HashMap::new()));
);
static PROC_INC: AtomicUsize = AtomicUsize::new(0);
pub fn add_proc(mut cmd: Command, msg: String) -> anyhow::Result<()> {
let mut proc = cmd.spawn()?;
let id = PROC_INC.fetch_add(1, Ordering::AcqRel);
tokio::spawn(async move {
let id = id;
proc.wait().await
.expect("child process encountered an error");
PROCESSES.lock().unwrap().write().unwrap().get_mut(&id).unwrap().finished = true;
});
PROCESSES.lock().unwrap().write().unwrap().insert(id, Proc {
finished: false,
msg,
});
Ok(())
}
pub fn proc_count() -> usize {
PROCESSES.lock().unwrap().read().unwrap().len()
}
pub fn is_proc_queue_full(max: usize) -> bool {
let proc_cnt = PROCESSES.lock().unwrap().read().unwrap().len();
proc_cnt >= max
}
pub fn purge_done_procs() -> usize {
let mut finish_count = 0;
let procs = {
PROCESSES.lock().unwrap().read().unwrap().clone()
};
for (idx, proc) in procs {
if proc.finished {
{
PROCESSES.lock().unwrap().write().unwrap().remove(&idx);
}
log::info!("{}", proc.msg);
finish_count += 1;
}
}
finish_count
}
/// Waits for processes to finish until the proc count is lower or equal to `max`
pub fn wait_for_procs_until(max: usize) -> anyhow::Result<usize> {
// NOTE: This looks really fucked because i dont want to deadlock the processes so i lock PROCESSES for as little as possible
// NOTE: So its also kinda really slow
let mut finish_count = 0;
loop {
if !is_proc_queue_full(max) {
return Ok(finish_count);
}
finish_count += purge_done_procs();
}
}