Skip to main content

veilid_tools/async_locks/
async_semaphore.rs

1//! AsyncSemaphore
2use super::*;
3
4use async_lock::Semaphore as InnerAsyncSemaphore;
5use async_lock::SemaphoreGuard as InnerAsyncSemaphoreGuard;
6use async_lock::SemaphoreGuardArc as InnerAsyncSemaphoreGuardArc;
7
8#[derive(Debug)]
9pub struct AsyncSemaphore {
10    inner: Arc<InnerAsyncSemaphore>,
11    #[cfg(feature = "debug-locks")]
12    lock_id_container: LockIdContainer,
13}
14
15impl AsyncSemaphore {
16    #[inline]
17    #[must_use]
18    pub fn new(n: usize) -> AsyncSemaphore {
19        AsyncSemaphore {
20            inner: Arc::new(InnerAsyncSemaphore::new(n)),
21            #[cfg(feature = "debug-locks")]
22            lock_id_container: LockIdContainer::next(),
23        }
24    }
25
26    #[inline]
27    #[must_use]
28    pub fn try_acquire(&self) -> Option<AsyncSemaphoreGuard<'_>> {
29        let inner = self.inner.try_acquire()?;
30        let out = AsyncSemaphoreGuard {
31            inner,
32            #[cfg(feature = "debug-locks")]
33            _guard_id_container: GuardIdContainer::next(
34                self.lock_id_container.clone(),
35                #[cfg(feature = "debug-locks-detect")]
36                LockSense::TryWrite,
37            ),
38        };
39
40        Some(out)
41    }
42
43    #[inline]
44    #[must_use]
45    pub async fn acquire(&self) -> AsyncSemaphoreGuard<'_> {
46        cfg_if! {
47            if #[cfg(feature = "debug-locks")] {
48                let inner = match timeout(DEBUG_LOCKS_DURATION_MS, self.inner.acquire()).await {
49                    Ok(v) => v,
50                    Err(_) => {
51                        self.lock_id_container.report_deadlock("AsyncSemaphore::acquire deadlock");
52                    }
53                };
54            } else {
55                let inner = self.inner.acquire().await;
56            }
57        }
58
59        AsyncSemaphoreGuard {
60            inner,
61            #[cfg(feature = "debug-locks")]
62            _guard_id_container: GuardIdContainer::next(
63                self.lock_id_container.clone(),
64                #[cfg(feature = "debug-locks-detect")]
65                LockSense::Write,
66            ),
67        }
68    }
69
70    #[inline]
71    #[must_use]
72    pub fn try_acquire_arc(self: &Arc<Self>) -> Option<AsyncSemaphoreGuardArc> {
73        let inner = self.inner.try_acquire_arc()?;
74        let out = AsyncSemaphoreGuardArc {
75            inner,
76            #[cfg(feature = "debug-locks")]
77            _guard_id_container: GuardIdContainer::next(
78                self.lock_id_container.clone(),
79                #[cfg(feature = "debug-locks-detect")]
80                LockSense::TryWrite,
81            ),
82        };
83
84        Some(out)
85    }
86
87    #[inline]
88    #[must_use]
89    pub async fn acquire_arc(self: &Arc<Self>) -> AsyncSemaphoreGuardArc {
90        cfg_if! {
91            if #[cfg(feature = "debug-locks")] {
92                let inner = match timeout(DEBUG_LOCKS_DURATION_MS, self.inner.acquire_arc()).await {
93                    Ok(v) => v,
94                    Err(_) => {
95                        self.lock_id_container.report_deadlock("AsyncSemaphore::acquire_arc deadlock");
96                    }
97                };
98            } else {
99                let inner = self.inner.acquire_arc().await;
100            }
101        }
102
103        AsyncSemaphoreGuardArc {
104            inner,
105            #[cfg(feature = "debug-locks")]
106            _guard_id_container: GuardIdContainer::next(
107                self.lock_id_container.clone(),
108                #[cfg(feature = "debug-locks-detect")]
109                LockSense::Write,
110            ),
111        }
112    }
113}
114
115#[clippy::has_significant_drop]
116#[derive(Debug)]
117pub struct AsyncSemaphoreGuard<'a> {
118    #[allow(dead_code)]
119    inner: InnerAsyncSemaphoreGuard<'a>,
120    #[cfg(feature = "debug-locks")]
121    _guard_id_container: GuardIdContainer,
122}
123
124/// An owned guard that releases the acquired permit.
125#[clippy::has_significant_drop]
126#[derive(Debug)]
127pub struct AsyncSemaphoreGuardArc {
128    #[allow(dead_code)]
129    inner: InnerAsyncSemaphoreGuardArc,
130    #[cfg(feature = "debug-locks")]
131    _guard_id_container: GuardIdContainer,
132}