use std::sync::{Arc, Condvar, Mutex};
use nodedb_types::DatabaseId;
#[derive(Debug, Default)]
struct Slot {
remaining: usize,
started: bool,
done: bool,
}
#[derive(Debug)]
pub struct CloneMaterializerHandle {
db_id: DatabaseId,
inner: Arc<(Mutex<Slot>, Condvar)>,
}
impl CloneMaterializerHandle {
pub fn new(db_id: DatabaseId) -> Self {
Self {
db_id,
inner: Arc::new((Mutex::new(Slot::default()), Condvar::new())),
}
}
pub fn database_id(&self) -> DatabaseId {
self.db_id
}
pub fn clone_arc(&self) -> Self {
Self {
db_id: self.db_id,
inner: Arc::clone(&self.inner),
}
}
pub fn notify_start(&self, collection_count: usize) {
let (lock, cvar) = &*self.inner;
let mut slot = lock.lock().unwrap_or_else(|p| p.into_inner());
if slot.started {
return;
}
slot.started = true;
slot.remaining = collection_count;
if collection_count == 0 {
slot.done = true;
cvar.notify_all();
}
}
pub fn notify_collection_done(&self) {
let (lock, cvar) = &*self.inner;
let mut slot = lock.lock().unwrap_or_else(|p| p.into_inner());
if slot.remaining > 0 {
slot.remaining -= 1;
}
if slot.started && slot.remaining == 0 {
slot.done = true;
cvar.notify_all();
}
}
pub fn wait_until_done(&self) {
let (lock, cvar) = &*self.inner;
let mut slot = lock.lock().unwrap_or_else(|p| p.into_inner());
while !slot.done {
slot = cvar.wait(slot).unwrap_or_else(|p| p.into_inner());
}
}
pub fn is_done(&self) -> bool {
let (lock, _) = &*self.inner;
let slot = lock.lock().unwrap_or_else(|p| p.into_inner());
slot.done
}
}