From 33262c98c6292c325eebeed260e1d6cf70361f26 Mon Sep 17 00:00:00 2001 From: Elaina Claus Date: Sun, 4 May 2025 19:51:31 -0400 Subject: [PATCH] add a parking lot impl --- src/busy_lot.rs | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/busy_lot.rs diff --git a/src/busy_lot.rs b/src/busy_lot.rs new file mode 100644 index 0000000..83686d2 --- /dev/null +++ b/src/busy_lot.rs @@ -0,0 +1,40 @@ +use std::sync::Arc; +use std::sync::atomic::{AtomicUsize, Ordering}; + +/// Shared, lock-free counter of active jobs. +/// Cloning is cheap (Arc); dropping a ticket auto-decrements. +#[derive(Clone)] +pub struct BusyLot { + inner: Arc, +} + +/// RAII ticket returned from `BusyLot::park()`. +/// When the ticket is dropped (even on panic) the lot counter goes down. +pub struct Ticket { + lot: BusyLot, +} + +impl BusyLot { + pub fn new() -> Self { + Self { + inner: Arc::new(AtomicUsize::new(0)), + } + } + + /// Takes a parking space and returns a ticket. + pub fn park(&self) -> Ticket { + self.inner.fetch_add(1, Ordering::AcqRel); + Ticket { lot: self.clone() } + } + + /// `true` if at least one ticket is still parked. + pub fn is_busy(&self) -> bool { + self.inner.load(Ordering::Acquire) != 0 + } +} + +impl Drop for Ticket { + fn drop(&mut self) { + self.lot.inner.fetch_sub(1, Ordering::AcqRel); + } +}