veilid_tools/async_locks/
async_semaphore.rs1use 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#[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}