use std::sync::{atomic::AtomicUsize, Arc}; pub struct Limiter { limit: usize, counter: Arc, } impl Limiter { pub fn new(limit: usize) -> Self { Limiter { counter: Default::default(), limit, } } pub fn obtain(&self) -> Option { let c = self .counter .fetch_add(1, std::sync::atomic::Ordering::Relaxed); if c < self.limit { Some(LimitLock { counter: self.counter.clone(), }) } else { None } } } pub struct LimitLock { counter: Arc, } impl Drop for LimitLock { fn drop(&mut self) { self.counter .fetch_sub(1, std::sync::atomic::Ordering::Relaxed); } }