2024-09-14 13:50:07 +00:00
|
|
|
use std::{collections::HashMap, sync::{atomic::{AtomicUsize, Ordering}, Mutex, RwLock}};
|
2024-04-22 16:14:48 +00:00
|
|
|
|
2024-09-14 13:50:07 +00:00
|
|
|
use tokio::process::Command;
|
2024-04-22 16:14:48 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[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);
|
|
|
|
|
|
|
|
|
2024-09-14 13:50:07 +00:00
|
|
|
pub fn add_proc(mut cmd: Command, msg: String) -> anyhow::Result<()> {
|
2024-04-22 16:14:48 +00:00
|
|
|
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");
|
2024-09-14 13:50:07 +00:00
|
|
|
PROCESSES.lock().unwrap().write().unwrap().get_mut(&id).unwrap().finished = true;
|
2024-04-22 16:14:48 +00:00
|
|
|
});
|
|
|
|
|
2024-09-14 13:50:07 +00:00
|
|
|
PROCESSES.lock().unwrap().write().unwrap().insert(id, Proc {
|
2024-04-22 16:14:48 +00:00
|
|
|
finished: false,
|
|
|
|
msg,
|
|
|
|
});
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2024-09-14 16:00:43 +00:00
|
|
|
pub fn proc_count() -> usize {
|
|
|
|
PROCESSES.lock().unwrap().read().unwrap().len()
|
|
|
|
}
|
2024-09-14 13:50:07 +00:00
|
|
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2024-10-09 12:02:24 +00:00
|
|
|
/// Waits for processes to finish until the proc count is lower or equal to `max`
|
2024-09-14 13:50:07 +00:00
|
|
|
pub fn wait_for_procs_untill(max: usize) -> anyhow::Result<usize> {
|
2024-04-22 16:14:48 +00:00
|
|
|
// 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 {
|
2024-09-14 13:50:07 +00:00
|
|
|
if !is_proc_queue_full(max) {
|
|
|
|
return Ok(finish_count);
|
2024-04-22 16:14:48 +00:00
|
|
|
}
|
2024-09-14 13:50:07 +00:00
|
|
|
finish_count += purge_done_procs();
|
2024-04-22 16:14:48 +00:00
|
|
|
}
|
2024-09-14 13:50:07 +00:00
|
|
|
}
|