use crate::resource::InsufficientBudgetError;
use crate::resource::ResourceLimit;
use crate::resource::ResourceQuantity;
use crate::resource::ResourceReleaseError;
#[derive(Debug, PartialEq, Eq)]
pub struct ResourcePool<R, Q = u64>
where
Q: ResourceQuantity,
{
limit: ResourceLimit<R, Q>,
available: Q,
}
impl<R, Q> ResourcePool<R, Q>
where
Q: ResourceQuantity,
{
#[inline]
#[must_use]
pub const fn new(resource: R, limit: Q) -> Self {
Self {
limit: ResourceLimit::new(resource, limit),
available: limit,
}
}
#[inline]
#[must_use]
pub fn from_limit(limit: ResourceLimit<R, Q>) -> Self {
let available = limit.maximum();
Self { limit, available }
}
pub fn try_acquire(&mut self, amount: Q) -> Result<(), InsufficientBudgetError<R, Q>>
where
R: Clone,
{
if amount > self.available {
return Err(InsufficientBudgetError {
resource: self.limit.resource().clone(),
limit: self.limit.maximum(),
remaining: self.available,
requested: amount,
});
}
self.available = self.available - amount;
Ok(())
}
pub fn release(&mut self, amount: Q) -> Result<(), ResourceReleaseError<R, Q>>
where
R: Clone,
{
let in_use = self.in_use();
if amount > in_use {
return Err(ResourceReleaseError::InvalidRelease {
resource: self.limit.resource().clone(),
limit: self.limit.maximum(),
in_use,
requested: amount,
});
}
self.available = self.available + amount;
Ok(())
}
#[must_use]
#[inline(always)]
pub const fn resource(&self) -> &R {
self.limit.resource()
}
#[must_use]
#[inline(always)]
pub const fn resource_limit(&self) -> &ResourceLimit<R, Q> {
&self.limit
}
#[must_use]
#[inline(always)]
pub const fn capacity(&self) -> Q {
self.limit.maximum()
}
#[must_use]
#[inline(always)]
pub const fn available(&self) -> Q {
self.available
}
#[inline(always)]
#[must_use]
pub fn in_use(&self) -> Q {
self.limit.maximum() - self.available
}
}