use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;
#[derive(Clone, Default)]
pub struct SlotCounter {
busy: Arc<AtomicUsize>,
}
impl SlotCounter {
pub fn new() -> Self {
Self::default()
}
pub fn busy(&self) -> usize {
self.busy.load(Ordering::Relaxed)
}
pub fn reserve(&self) -> Reservation {
self.busy.fetch_add(1, Ordering::Relaxed);
Reservation {
busy: self.busy.clone(),
}
}
}
pub struct Reservation {
busy: Arc<AtomicUsize>,
}
impl Drop for Reservation {
fn drop(&mut self) {
self.busy.fetch_sub(1, Ordering::Relaxed);
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn busy_starts_at_zero() {
let c = SlotCounter::new();
assert_eq!(c.busy(), 0);
}
#[test]
fn reservation_increments_and_drops_decrement() {
let c = SlotCounter::new();
let r1 = c.reserve();
assert_eq!(c.busy(), 1);
let r2 = c.reserve();
assert_eq!(c.busy(), 2);
drop(r2);
assert_eq!(c.busy(), 1);
drop(r1);
assert_eq!(c.busy(), 0);
}
}