use std::sync::Arc;
use super::ManagedResourcePermit;
use super::internal::ManagedResourcePoolInner;
use crate::resource::InsufficientBudgetError;
use crate::resource::ResourceLimit;
use crate::resource::ResourceQuantity;
#[derive(Debug)]
pub struct ManagedResourcePool<R, Q = u64>
where
Q: ResourceQuantity,
{
inner: Arc<ManagedResourcePoolInner<R, Q>>,
}
impl<R, Q> Clone for ManagedResourcePool<R, Q>
where
Q: ResourceQuantity,
{
fn clone(&self) -> Self {
Self {
inner: Arc::clone(&self.inner),
}
}
}
impl<R, Q> ManagedResourcePool<R, Q>
where
Q: ResourceQuantity,
{
#[must_use]
#[inline]
pub fn new(resource: R, limit: Q) -> Self {
Self::from_limit(ResourceLimit::new(resource, limit))
}
#[must_use]
#[inline]
pub fn from_limit(limit: ResourceLimit<R, Q>) -> Self {
Self {
inner: Arc::new(ManagedResourcePoolInner::new(limit)),
}
}
pub fn try_acquire(&self, amount: Q) -> Result<ManagedResourcePermit<R, Q>, InsufficientBudgetError<R, Q>>
where
R: Clone,
{
let remaining = {
let mut available = self.inner.lock_available();
if amount <= *available {
*available = *available - amount;
return Ok(ManagedResourcePermit::new(Arc::clone(&self.inner), amount));
}
*available
};
Err(InsufficientBudgetError {
resource: self.resource().clone(),
limit: self.capacity(),
remaining,
requested: amount,
})
}
#[must_use]
#[inline(always)]
pub fn resource(&self) -> &R {
self.inner.limit.resource()
}
#[must_use]
#[inline(always)]
pub fn resource_limit(&self) -> &ResourceLimit<R, Q> {
&self.inner.limit
}
#[must_use]
#[inline(always)]
pub fn capacity(&self) -> Q {
self.inner.limit.maximum()
}
#[must_use]
#[inline(always)]
pub fn available(&self) -> Q {
*self.inner.lock_available()
}
#[must_use]
#[inline(always)]
pub fn in_use(&self) -> Q {
self.capacity() - self.available()
}
}