use std::sync::{Arc, Mutex, Weak};
use crate::job::Job;
#[derive(Default)]
pub(crate) struct Registry {
weaks: Mutex<Vec<Weak<Job>>>,
}
impl Registry {
pub(crate) fn track(&self, job: &Arc<Job>) {
let mut w = self.weaks.lock().expect("registry mutex poisoned");
w.push(Arc::downgrade(job));
}
pub(crate) fn peek_idle(&self) -> Option<Arc<Job>> {
let mut w = self.weaks.lock().expect("registry mutex poisoned");
w.retain(|wk| wk.strong_count() > 0);
for wk in w.iter() {
if let Some(arc) = wk.upgrade() {
let n = arc.in_flight();
if n == u32::MAX {
continue;
}
if n == 0 && Arc::strong_count(&arc) == 2 {
return Some(arc);
}
}
}
None
}
pub(crate) fn least_busy(&self, limit: usize) -> Vec<Arc<Job>> {
let mut live: Vec<(u32, Arc<Job>)> = {
let mut w = self.weaks.lock().expect("registry mutex poisoned");
w.retain(|wk| wk.strong_count() > 0);
w.iter()
.filter_map(Weak::upgrade)
.filter_map(|arc| {
let n = arc.in_flight();
if n == u32::MAX { None } else { Some((n, arc)) }
})
.collect()
};
live.sort_by_key(|(n, _)| *n);
live.into_iter().take(limit).map(|(_, a)| a).collect()
}
}