use std::sync::Arc;
use tokio::sync::{OwnedSemaphorePermit, Semaphore};
use crate::error::ToolkitError;
#[derive(Clone, Debug)]
pub struct Bulkhead {
sem: Arc<Semaphore>,
capacity: usize,
}
pub struct BulkheadPermit(#[allow(dead_code)] OwnedSemaphorePermit);
impl std::fmt::Debug for BulkheadPermit {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("BulkheadPermit").finish()
}
}
impl Bulkhead {
pub fn new(capacity: usize) -> Self {
assert!(capacity > 0, "capacity must be > 0");
Self {
sem: Arc::new(Semaphore::new(capacity)),
capacity,
}
}
pub async fn acquire(&self) -> Result<BulkheadPermit, ToolkitError> {
match self.sem.clone().acquire_owned().await {
Ok(p) => Ok(BulkheadPermit(p)),
Err(_) => Err(ToolkitError::BulkheadClosed),
}
}
pub fn try_acquire(&self) -> Option<BulkheadPermit> {
self.sem
.clone()
.try_acquire_owned()
.ok()
.map(BulkheadPermit)
}
pub fn available_permits(&self) -> usize {
self.sem.available_permits()
}
pub fn capacity(&self) -> usize {
self.capacity
}
pub fn close(&self) {
self.sem.close();
}
}