use std::sync::atomic::{
AtomicI64,
Ordering::{AcqRel, Acquire, Release},
};
pub(crate) struct Budget {
total: i64,
used: AtomicI64,
}
impl Budget {
#[inline]
pub(crate) const fn new(total: i64) -> Self {
Self {
total,
used: AtomicI64::new(0),
}
}
#[inline]
pub(crate) fn try_reserve(&self, bytes: i64) -> bool {
let mut cur = self.used.load(Acquire);
loop {
let next = cur.saturating_add(bytes);
if next > self.total {
return false;
}
match self.used.compare_exchange_weak(cur, next, AcqRel, Acquire) {
Ok(_) => return true,
Err(v) => cur = v,
}
}
}
#[inline]
pub(crate) fn release(&self, bytes: i64) {
self.used.fetch_sub(bytes, Release);
}
#[inline]
pub(crate) fn used(&self) -> i64 {
self.used.load(Acquire)
}
#[inline]
pub(crate) const fn total(&self) -> i64 {
self.total
}
}