use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;
pub struct ConnectionPool {
active: AtomicUsize,
max: usize,
}
impl ConnectionPool {
pub fn new(max_connections: usize) -> Self {
Self {
active: AtomicUsize::new(0),
max: max_connections,
}
}
pub fn try_acquire(&self) -> bool {
loop {
let current = self.active.load(Ordering::Relaxed);
if current >= self.max {
return false;
}
if self
.active
.compare_exchange(current, current + 1, Ordering::AcqRel, Ordering::Relaxed)
.is_ok()
{
return true;
}
}
}
pub fn release(&self) {
self.active.fetch_sub(1, Ordering::AcqRel);
}
pub fn active_count(&self) -> usize {
self.active.load(Ordering::Relaxed)
}
pub fn max_connections(&self) -> usize {
self.max
}
}
pub struct ConnectionGuard {
pool: Arc<ConnectionPool>,
}
impl ConnectionGuard {
pub fn new(pool: Arc<ConnectionPool>) -> Option<Self> {
if pool.try_acquire() {
Some(Self { pool })
} else {
None
}
}
}
impl Drop for ConnectionGuard {
fn drop(&mut self) {
self.pool.release();
}
}