use std::cell::Cell;
use std::rc::Rc;
use super::pubsub::PubSub;
#[derive(Clone, Default)]
pub struct InFlight(Rc<InFlightData>);
#[derive(Default)]
struct InFlightData {
count: Cell<u32>,
changed: PubSub<u32>,
}
#[must_use]
pub struct InFlightGuard(InFlight);
impl InFlight {
pub fn guard(&self) -> InFlightGuard {
let count = self.0.count.get() + 1;
self.0.count.set(count);
self.0.changed.emit(count);
InFlightGuard(self.clone())
}
pub fn count(&self) -> u32 {
self.0.count.get()
}
pub fn is_empty(&self) -> bool {
self.0.count.get() == 0
}
pub fn changed(&self) -> &PubSub<u32> {
&self.0.changed
}
pub async fn settle(&self) {
while self.0.count.get() > 0 {
if self.0.changed.read_next().await.is_err() {
break;
}
}
}
}
impl Drop for InFlightGuard {
fn drop(&mut self) {
let data = &self.0.0;
let count = data.count.get();
debug_assert!(count > 0, "InFlight underflow");
let count = count.saturating_sub(1);
data.count.set(count);
data.changed.emit(count);
}
}