1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
use tokio::sync::Semaphore as SemaphoreBase;
use tokio::sync::SemaphorePermit as SemaphoreBasePermit;

/// A semaphore maintains a set of permits. Permits are used to synchronize access to a shared resource.
/// A semaphore differs from a mutex in that it can allow more than one concurrent caller to access the shared resource at a time.
pub struct Semaphore {
    semaphore: SemaphoreBase,
}

/// Represents a permit to a [Semaphore].
pub struct SemaphorePermit<'a> {
    _permit: SemaphoreBasePermit<'a>,
}

/// Error when there are no permits available.
#[derive(Debug)]
pub struct NoPermits;

impl Semaphore {
    /// Creates a new instance of [Semaphore] with the given `permits` count.
    pub const fn new(permits: usize) -> Self {
        Self {
            semaphore: SemaphoreBase::const_new(permits),
        }
    }

    /// Acquires one permit asynchronously waiting for one to become available.
    #[must_use]
    pub async fn acquire(&self) -> SemaphorePermit {
        let permit = self.semaphore.acquire().await.unwrap();

        SemaphorePermit { _permit: permit }
    }

    /// Acquires many permits asynchronously waiting for them to become available.
    #[must_use]
    pub async fn acquire_many(&self, count: u32) -> SemaphorePermit {
        let permit = self.semaphore.acquire_many(count).await.unwrap();

        SemaphorePermit { _permit: permit }
    }

    /// Attempts to acquire a permit, returning an error if there are none available.
    pub fn try_acquire(&self) -> Result<SemaphorePermit, NoPermits> {
        let permit = self.semaphore.try_acquire().map_err(|_| NoPermits)?;

        Ok(SemaphorePermit { _permit: permit })
    }
}