flag_bearer/
permit.rs

1use std::sync::Arc;
2
3use crate::{IsCloseable, Semaphore, SemaphoreState, Uncloseable, drop_wrapper::DropWrapper};
4
5/// The drop-guard for semaphore permits.
6/// Will ensure the permit is released when dropped.
7#[must_use]
8pub struct Permit<'a, S, C = Uncloseable>
9where
10    S: SemaphoreState + ?Sized,
11    C: IsCloseable,
12{
13    inner: DropWrapper<SemWrapper<'a, S, C>>,
14}
15
16impl<S, C> core::fmt::Debug for Permit<'_, S, C>
17where
18    S: SemaphoreState + ?Sized,
19    C: IsCloseable,
20    S::Permit: core::fmt::Debug,
21{
22    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
23        f.debug_struct("Permit")
24            .field("permit", &self.inner.t)
25            .finish_non_exhaustive()
26    }
27}
28
29impl<S, C> core::ops::Deref for Permit<'_, S, C>
30where
31    S: SemaphoreState + ?Sized,
32    C: IsCloseable,
33{
34    type Target = S::Permit;
35    fn deref(&self) -> &Self::Target {
36        &self.inner.t
37    }
38}
39
40impl<S, C> core::ops::DerefMut for Permit<'_, S, C>
41where
42    S: SemaphoreState + ?Sized,
43    C: IsCloseable,
44{
45    fn deref_mut(&mut self) -> &mut Self::Target {
46        &mut self.inner.t
47    }
48}
49
50impl<'a, S, C> Permit<'a, S, C>
51where
52    S: SemaphoreState + ?Sized,
53    C: IsCloseable,
54{
55    /// Construct a new permit out of thin air, no waiting is required.
56    ///
57    /// This can violate the purpose of the semaphore, but is provided for convenience.
58    /// It can be used to introduce new permits to the semaphore if desired, or it can be
59    /// paired with [`Permit::take`] for niche use-cases where the semaphore lifetime
60    /// gets in the way.
61    pub fn out_of_thin_air(sem: &'a Semaphore<S, C>, permit: S::Permit) -> Self {
62        Self {
63            inner: DropWrapper::new(SemWrapper { sem }, permit),
64        }
65    }
66
67    /// Get access to the associated semaphore
68    pub fn semaphore(this: &Self) -> &'a Semaphore<S, C> {
69        this.inner.s.sem
70    }
71
72    /// Do not release the permit to the semaphore.
73    pub fn take(this: Self) -> S::Permit {
74        this.inner.take()
75    }
76
77    /// Upgrade this permit into an [`OwnedPermit`].
78    pub fn into_owned_permit(self, sem: Arc<Semaphore<S, C>>) -> OwnedPermit<S, C> {
79        debug_assert_eq!(
80            Arc::as_ptr(&sem),
81            core::ptr::from_ref(Self::semaphore(&self)),
82            "semaphore mismatch!"
83        );
84        OwnedPermit {
85            inner: DropWrapper::new(SemWrapperOwned { sem }, Self::take(self)),
86        }
87    }
88}
89
90struct SemWrapper<'a, S: SemaphoreState + ?Sized, C: IsCloseable> {
91    sem: &'a Semaphore<S, C>,
92}
93
94impl<S: SemaphoreState + ?Sized, C: IsCloseable> crate::drop_wrapper::Drop2
95    for SemWrapper<'_, S, C>
96{
97    type T = S::Permit;
98
99    fn drop(&mut self, permit: Self::T) {
100        self.sem.with_state(|s| s.release(permit));
101    }
102}
103
104/// The drop-guard for owned semaphore permits.
105/// Will ensure the permit is released when dropped.
106#[must_use]
107pub struct OwnedPermit<S, C = Uncloseable>
108where
109    S: SemaphoreState + ?Sized,
110    C: IsCloseable,
111{
112    inner: DropWrapper<SemWrapperOwned<S, C>>,
113}
114
115impl<S, C> core::fmt::Debug for OwnedPermit<S, C>
116where
117    S: SemaphoreState + ?Sized,
118    C: IsCloseable,
119    S::Permit: core::fmt::Debug,
120{
121    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
122        f.debug_struct("Permit")
123            .field("permit", &self.inner.t)
124            .finish_non_exhaustive()
125    }
126}
127
128impl<S, C> core::ops::Deref for OwnedPermit<S, C>
129where
130    S: SemaphoreState + ?Sized,
131    C: IsCloseable,
132{
133    type Target = S::Permit;
134    fn deref(&self) -> &Self::Target {
135        &self.inner.t
136    }
137}
138
139impl<S, C> core::ops::DerefMut for OwnedPermit<S, C>
140where
141    S: SemaphoreState + ?Sized,
142    C: IsCloseable,
143{
144    fn deref_mut(&mut self) -> &mut Self::Target {
145        &mut self.inner.t
146    }
147}
148
149impl<S, C> OwnedPermit<S, C>
150where
151    S: SemaphoreState + ?Sized,
152    C: IsCloseable,
153{
154    /// Construct a new permit out of thin air, no waiting is required.
155    ///
156    /// This can violate the purpose of the semaphore, but is provided for convenience.
157    /// It can be used to introduce new permits to the semaphore if desired, or it can be
158    /// paired with [`Permit::take`] for niche use-cases where the semaphore lifetime
159    /// gets in the way.
160    pub fn out_of_thin_air(sem: Arc<Semaphore<S, C>>, permit: S::Permit) -> Self {
161        Self {
162            inner: DropWrapper::new(SemWrapperOwned { sem }, permit),
163        }
164    }
165
166    /// Get access to the associated semaphore
167    pub fn semaphore(this: &Self) -> &Arc<Semaphore<S, C>> {
168        &this.inner.s.sem
169    }
170
171    /// Do not release the permit to the semaphore.
172    pub fn take(this: Self) -> S::Permit {
173        this.inner.take()
174    }
175}
176
177struct SemWrapperOwned<S: SemaphoreState + ?Sized, C: IsCloseable> {
178    sem: Arc<Semaphore<S, C>>,
179}
180
181impl<S: SemaphoreState + ?Sized, C: IsCloseable> crate::drop_wrapper::Drop2
182    for SemWrapperOwned<S, C>
183{
184    type T = S::Permit;
185
186    fn drop(&mut self, permit: Self::T) {
187        self.sem.with_state(|s| s.release(permit));
188    }
189}