• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use super::batch_semaphore as ll; // low level implementation
2 use super::{AcquireError, TryAcquireError};
3 #[cfg(all(tokio_unstable, feature = "tracing"))]
4 use crate::util::trace;
5 use std::sync::Arc;
6 
7 /// Counting semaphore performing asynchronous permit acquisition.
8 ///
9 /// A semaphore maintains a set of permits. Permits are used to synchronize
10 /// access to a shared resource. A semaphore differs from a mutex in that it
11 /// can allow more than one concurrent caller to access the shared resource at a
12 /// time.
13 ///
14 /// When `acquire` is called and the semaphore has remaining permits, the
15 /// function immediately returns a permit. However, if no remaining permits are
16 /// available, `acquire` (asynchronously) waits until an outstanding permit is
17 /// dropped. At this point, the freed permit is assigned to the caller.
18 ///
19 /// This `Semaphore` is fair, which means that permits are given out in the order
20 /// they were requested. This fairness is also applied when `acquire_many` gets
21 /// involved, so if a call to `acquire_many` at the front of the queue requests
22 /// more permits than currently available, this can prevent a call to `acquire`
23 /// from completing, even if the semaphore has enough permits complete the call
24 /// to `acquire`.
25 ///
26 /// To use the `Semaphore` in a poll function, you can use the [`PollSemaphore`]
27 /// utility.
28 ///
29 /// # Examples
30 ///
31 /// Basic usage:
32 ///
33 /// ```
34 /// use tokio::sync::{Semaphore, TryAcquireError};
35 ///
36 /// #[tokio::main]
37 /// async fn main() {
38 ///     let semaphore = Semaphore::new(3);
39 ///
40 ///     let a_permit = semaphore.acquire().await.unwrap();
41 ///     let two_permits = semaphore.acquire_many(2).await.unwrap();
42 ///
43 ///     assert_eq!(semaphore.available_permits(), 0);
44 ///
45 ///     let permit_attempt = semaphore.try_acquire();
46 ///     assert_eq!(permit_attempt.err(), Some(TryAcquireError::NoPermits));
47 /// }
48 /// ```
49 ///
50 /// Use [`Semaphore::acquire_owned`] to move permits across tasks:
51 ///
52 /// ```
53 /// use std::sync::Arc;
54 /// use tokio::sync::Semaphore;
55 ///
56 /// #[tokio::main]
57 /// async fn main() {
58 ///     let semaphore = Arc::new(Semaphore::new(3));
59 ///     let mut join_handles = Vec::new();
60 ///
61 ///     for _ in 0..5 {
62 ///         let permit = semaphore.clone().acquire_owned().await.unwrap();
63 ///         join_handles.push(tokio::spawn(async move {
64 ///             // perform task...
65 ///             // explicitly own `permit` in the task
66 ///             drop(permit);
67 ///         }));
68 ///     }
69 ///
70 ///     for handle in join_handles {
71 ///         handle.await.unwrap();
72 ///     }
73 /// }
74 /// ```
75 ///
76 /// [`PollSemaphore`]: https://docs.rs/tokio-util/latest/tokio_util/sync/struct.PollSemaphore.html
77 /// [`Semaphore::acquire_owned`]: crate::sync::Semaphore::acquire_owned
78 #[derive(Debug)]
79 pub struct Semaphore {
80     /// The low level semaphore
81     ll_sem: ll::Semaphore,
82     #[cfg(all(tokio_unstable, feature = "tracing"))]
83     resource_span: tracing::Span,
84 }
85 
86 /// A permit from the semaphore.
87 ///
88 /// This type is created by the [`acquire`] method.
89 ///
90 /// [`acquire`]: crate::sync::Semaphore::acquire()
91 #[must_use]
92 #[clippy::has_significant_drop]
93 #[derive(Debug)]
94 pub struct SemaphorePermit<'a> {
95     sem: &'a Semaphore,
96     permits: u32,
97 }
98 
99 /// An owned permit from the semaphore.
100 ///
101 /// This type is created by the [`acquire_owned`] method.
102 ///
103 /// [`acquire_owned`]: crate::sync::Semaphore::acquire_owned()
104 #[must_use]
105 #[clippy::has_significant_drop]
106 #[derive(Debug)]
107 pub struct OwnedSemaphorePermit {
108     sem: Arc<Semaphore>,
109     permits: u32,
110 }
111 
112 #[test]
113 #[cfg(not(loom))]
bounds()114 fn bounds() {
115     fn check_unpin<T: Unpin>() {}
116     // This has to take a value, since the async fn's return type is unnameable.
117     fn check_send_sync_val<T: Send + Sync>(_t: T) {}
118     fn check_send_sync<T: Send + Sync>() {}
119     check_unpin::<Semaphore>();
120     check_unpin::<SemaphorePermit<'_>>();
121     check_send_sync::<Semaphore>();
122 
123     let semaphore = Semaphore::new(0);
124     check_send_sync_val(semaphore.acquire());
125 }
126 
127 impl Semaphore {
128     /// The maximum number of permits which a semaphore can hold. It is `usize::MAX >> 3`.
129     ///
130     /// Exceeding this limit typically results in a panic.
131     pub const MAX_PERMITS: usize = super::batch_semaphore::Semaphore::MAX_PERMITS;
132 
133     /// Creates a new semaphore with the initial number of permits.
134     ///
135     /// Panics if `permits` exceeds [`Semaphore::MAX_PERMITS`].
136     #[track_caller]
new(permits: usize) -> Self137     pub fn new(permits: usize) -> Self {
138         #[cfg(all(tokio_unstable, feature = "tracing"))]
139         let resource_span = {
140             let location = std::panic::Location::caller();
141 
142             tracing::trace_span!(
143                 "runtime.resource",
144                 concrete_type = "Semaphore",
145                 kind = "Sync",
146                 loc.file = location.file(),
147                 loc.line = location.line(),
148                 loc.col = location.column(),
149                 inherits_child_attrs = true,
150             )
151         };
152 
153         #[cfg(all(tokio_unstable, feature = "tracing"))]
154         let ll_sem = resource_span.in_scope(|| ll::Semaphore::new(permits));
155 
156         #[cfg(any(not(tokio_unstable), not(feature = "tracing")))]
157         let ll_sem = ll::Semaphore::new(permits);
158 
159         Self {
160             ll_sem,
161             #[cfg(all(tokio_unstable, feature = "tracing"))]
162             resource_span,
163         }
164     }
165 
166     /// Creates a new semaphore with the initial number of permits.
167     ///
168     /// # Examples
169     ///
170     /// ```
171     /// use tokio::sync::Semaphore;
172     ///
173     /// static SEM: Semaphore = Semaphore::const_new(10);
174     /// ```
175     #[cfg(not(all(loom, test)))]
const_new(permits: usize) -> Self176     pub const fn const_new(permits: usize) -> Self {
177         Self {
178             ll_sem: ll::Semaphore::const_new(permits),
179             #[cfg(all(tokio_unstable, feature = "tracing"))]
180             resource_span: tracing::Span::none(),
181         }
182     }
183 
184     /// Creates a new closed semaphore with 0 permits.
new_closed() -> Self185     pub(crate) fn new_closed() -> Self {
186         Self {
187             ll_sem: ll::Semaphore::new_closed(),
188             #[cfg(all(tokio_unstable, feature = "tracing"))]
189             resource_span: tracing::Span::none(),
190         }
191     }
192 
193     /// Returns the current number of available permits.
available_permits(&self) -> usize194     pub fn available_permits(&self) -> usize {
195         self.ll_sem.available_permits()
196     }
197 
198     /// Adds `n` new permits to the semaphore.
199     ///
200     /// The maximum number of permits is [`Semaphore::MAX_PERMITS`], and this function will panic if the limit is exceeded.
add_permits(&self, n: usize)201     pub fn add_permits(&self, n: usize) {
202         self.ll_sem.release(n);
203     }
204 
205     /// Acquires a permit from the semaphore.
206     ///
207     /// If the semaphore has been closed, this returns an [`AcquireError`].
208     /// Otherwise, this returns a [`SemaphorePermit`] representing the
209     /// acquired permit.
210     ///
211     /// # Cancel safety
212     ///
213     /// This method uses a queue to fairly distribute permits in the order they
214     /// were requested. Cancelling a call to `acquire` makes you lose your place
215     /// in the queue.
216     ///
217     /// # Examples
218     ///
219     /// ```
220     /// use tokio::sync::Semaphore;
221     ///
222     /// #[tokio::main]
223     /// async fn main() {
224     ///     let semaphore = Semaphore::new(2);
225     ///
226     ///     let permit_1 = semaphore.acquire().await.unwrap();
227     ///     assert_eq!(semaphore.available_permits(), 1);
228     ///
229     ///     let permit_2 = semaphore.acquire().await.unwrap();
230     ///     assert_eq!(semaphore.available_permits(), 0);
231     ///
232     ///     drop(permit_1);
233     ///     assert_eq!(semaphore.available_permits(), 1);
234     /// }
235     /// ```
236     ///
237     /// [`AcquireError`]: crate::sync::AcquireError
238     /// [`SemaphorePermit`]: crate::sync::SemaphorePermit
acquire(&self) -> Result<SemaphorePermit<'_>, AcquireError>239     pub async fn acquire(&self) -> Result<SemaphorePermit<'_>, AcquireError> {
240         #[cfg(all(tokio_unstable, feature = "tracing"))]
241         let inner = trace::async_op(
242             || self.ll_sem.acquire(1),
243             self.resource_span.clone(),
244             "Semaphore::acquire",
245             "poll",
246             true,
247         );
248         #[cfg(not(all(tokio_unstable, feature = "tracing")))]
249         let inner = self.ll_sem.acquire(1);
250 
251         inner.await?;
252         Ok(SemaphorePermit {
253             sem: self,
254             permits: 1,
255         })
256     }
257 
258     /// Acquires `n` permits from the semaphore.
259     ///
260     /// If the semaphore has been closed, this returns an [`AcquireError`].
261     /// Otherwise, this returns a [`SemaphorePermit`] representing the
262     /// acquired permits.
263     ///
264     /// # Cancel safety
265     ///
266     /// This method uses a queue to fairly distribute permits in the order they
267     /// were requested. Cancelling a call to `acquire_many` makes you lose your
268     /// place in the queue.
269     ///
270     /// # Examples
271     ///
272     /// ```
273     /// use tokio::sync::Semaphore;
274     ///
275     /// #[tokio::main]
276     /// async fn main() {
277     ///     let semaphore = Semaphore::new(5);
278     ///
279     ///     let permit = semaphore.acquire_many(3).await.unwrap();
280     ///     assert_eq!(semaphore.available_permits(), 2);
281     /// }
282     /// ```
283     ///
284     /// [`AcquireError`]: crate::sync::AcquireError
285     /// [`SemaphorePermit`]: crate::sync::SemaphorePermit
acquire_many(&self, n: u32) -> Result<SemaphorePermit<'_>, AcquireError>286     pub async fn acquire_many(&self, n: u32) -> Result<SemaphorePermit<'_>, AcquireError> {
287         #[cfg(all(tokio_unstable, feature = "tracing"))]
288         trace::async_op(
289             || self.ll_sem.acquire(n),
290             self.resource_span.clone(),
291             "Semaphore::acquire_many",
292             "poll",
293             true,
294         )
295         .await?;
296 
297         #[cfg(not(all(tokio_unstable, feature = "tracing")))]
298         self.ll_sem.acquire(n).await?;
299 
300         Ok(SemaphorePermit {
301             sem: self,
302             permits: n,
303         })
304     }
305 
306     /// Tries to acquire a permit from the semaphore.
307     ///
308     /// If the semaphore has been closed, this returns a [`TryAcquireError::Closed`]
309     /// and a [`TryAcquireError::NoPermits`] if there are no permits left. Otherwise,
310     /// this returns a [`SemaphorePermit`] representing the acquired permits.
311     ///
312     /// # Examples
313     ///
314     /// ```
315     /// use tokio::sync::{Semaphore, TryAcquireError};
316     ///
317     /// # fn main() {
318     /// let semaphore = Semaphore::new(2);
319     ///
320     /// let permit_1 = semaphore.try_acquire().unwrap();
321     /// assert_eq!(semaphore.available_permits(), 1);
322     ///
323     /// let permit_2 = semaphore.try_acquire().unwrap();
324     /// assert_eq!(semaphore.available_permits(), 0);
325     ///
326     /// let permit_3 = semaphore.try_acquire();
327     /// assert_eq!(permit_3.err(), Some(TryAcquireError::NoPermits));
328     /// # }
329     /// ```
330     ///
331     /// [`TryAcquireError::Closed`]: crate::sync::TryAcquireError::Closed
332     /// [`TryAcquireError::NoPermits`]: crate::sync::TryAcquireError::NoPermits
333     /// [`SemaphorePermit`]: crate::sync::SemaphorePermit
try_acquire(&self) -> Result<SemaphorePermit<'_>, TryAcquireError>334     pub fn try_acquire(&self) -> Result<SemaphorePermit<'_>, TryAcquireError> {
335         match self.ll_sem.try_acquire(1) {
336             Ok(_) => Ok(SemaphorePermit {
337                 sem: self,
338                 permits: 1,
339             }),
340             Err(e) => Err(e),
341         }
342     }
343 
344     /// Tries to acquire `n` permits from the semaphore.
345     ///
346     /// If the semaphore has been closed, this returns a [`TryAcquireError::Closed`]
347     /// and a [`TryAcquireError::NoPermits`] if there are not enough permits left.
348     /// Otherwise, this returns a [`SemaphorePermit`] representing the acquired permits.
349     ///
350     /// # Examples
351     ///
352     /// ```
353     /// use tokio::sync::{Semaphore, TryAcquireError};
354     ///
355     /// # fn main() {
356     /// let semaphore = Semaphore::new(4);
357     ///
358     /// let permit_1 = semaphore.try_acquire_many(3).unwrap();
359     /// assert_eq!(semaphore.available_permits(), 1);
360     ///
361     /// let permit_2 = semaphore.try_acquire_many(2);
362     /// assert_eq!(permit_2.err(), Some(TryAcquireError::NoPermits));
363     /// # }
364     /// ```
365     ///
366     /// [`TryAcquireError::Closed`]: crate::sync::TryAcquireError::Closed
367     /// [`TryAcquireError::NoPermits`]: crate::sync::TryAcquireError::NoPermits
368     /// [`SemaphorePermit`]: crate::sync::SemaphorePermit
try_acquire_many(&self, n: u32) -> Result<SemaphorePermit<'_>, TryAcquireError>369     pub fn try_acquire_many(&self, n: u32) -> Result<SemaphorePermit<'_>, TryAcquireError> {
370         match self.ll_sem.try_acquire(n) {
371             Ok(_) => Ok(SemaphorePermit {
372                 sem: self,
373                 permits: n,
374             }),
375             Err(e) => Err(e),
376         }
377     }
378 
379     /// Acquires a permit from the semaphore.
380     ///
381     /// The semaphore must be wrapped in an [`Arc`] to call this method.
382     /// If the semaphore has been closed, this returns an [`AcquireError`].
383     /// Otherwise, this returns a [`OwnedSemaphorePermit`] representing the
384     /// acquired permit.
385     ///
386     /// # Cancel safety
387     ///
388     /// This method uses a queue to fairly distribute permits in the order they
389     /// were requested. Cancelling a call to `acquire_owned` makes you lose your
390     /// place in the queue.
391     ///
392     /// # Examples
393     ///
394     /// ```
395     /// use std::sync::Arc;
396     /// use tokio::sync::Semaphore;
397     ///
398     /// #[tokio::main]
399     /// async fn main() {
400     ///     let semaphore = Arc::new(Semaphore::new(3));
401     ///     let mut join_handles = Vec::new();
402     ///
403     ///     for _ in 0..5 {
404     ///         let permit = semaphore.clone().acquire_owned().await.unwrap();
405     ///         join_handles.push(tokio::spawn(async move {
406     ///             // perform task...
407     ///             // explicitly own `permit` in the task
408     ///             drop(permit);
409     ///         }));
410     ///     }
411     ///
412     ///     for handle in join_handles {
413     ///         handle.await.unwrap();
414     ///     }
415     /// }
416     /// ```
417     ///
418     /// [`Arc`]: std::sync::Arc
419     /// [`AcquireError`]: crate::sync::AcquireError
420     /// [`OwnedSemaphorePermit`]: crate::sync::OwnedSemaphorePermit
acquire_owned(self: Arc<Self>) -> Result<OwnedSemaphorePermit, AcquireError>421     pub async fn acquire_owned(self: Arc<Self>) -> Result<OwnedSemaphorePermit, AcquireError> {
422         #[cfg(all(tokio_unstable, feature = "tracing"))]
423         let inner = trace::async_op(
424             || self.ll_sem.acquire(1),
425             self.resource_span.clone(),
426             "Semaphore::acquire_owned",
427             "poll",
428             true,
429         );
430         #[cfg(not(all(tokio_unstable, feature = "tracing")))]
431         let inner = self.ll_sem.acquire(1);
432 
433         inner.await?;
434         Ok(OwnedSemaphorePermit {
435             sem: self,
436             permits: 1,
437         })
438     }
439 
440     /// Acquires `n` permits from the semaphore.
441     ///
442     /// The semaphore must be wrapped in an [`Arc`] to call this method.
443     /// If the semaphore has been closed, this returns an [`AcquireError`].
444     /// Otherwise, this returns a [`OwnedSemaphorePermit`] representing the
445     /// acquired permit.
446     ///
447     /// # Cancel safety
448     ///
449     /// This method uses a queue to fairly distribute permits in the order they
450     /// were requested. Cancelling a call to `acquire_many_owned` makes you lose
451     /// your place in the queue.
452     ///
453     /// # Examples
454     ///
455     /// ```
456     /// use std::sync::Arc;
457     /// use tokio::sync::Semaphore;
458     ///
459     /// #[tokio::main]
460     /// async fn main() {
461     ///     let semaphore = Arc::new(Semaphore::new(10));
462     ///     let mut join_handles = Vec::new();
463     ///
464     ///     for _ in 0..5 {
465     ///         let permit = semaphore.clone().acquire_many_owned(2).await.unwrap();
466     ///         join_handles.push(tokio::spawn(async move {
467     ///             // perform task...
468     ///             // explicitly own `permit` in the task
469     ///             drop(permit);
470     ///         }));
471     ///     }
472     ///
473     ///     for handle in join_handles {
474     ///         handle.await.unwrap();
475     ///     }
476     /// }
477     /// ```
478     ///
479     /// [`Arc`]: std::sync::Arc
480     /// [`AcquireError`]: crate::sync::AcquireError
481     /// [`OwnedSemaphorePermit`]: crate::sync::OwnedSemaphorePermit
acquire_many_owned( self: Arc<Self>, n: u32, ) -> Result<OwnedSemaphorePermit, AcquireError>482     pub async fn acquire_many_owned(
483         self: Arc<Self>,
484         n: u32,
485     ) -> Result<OwnedSemaphorePermit, AcquireError> {
486         #[cfg(all(tokio_unstable, feature = "tracing"))]
487         let inner = trace::async_op(
488             || self.ll_sem.acquire(n),
489             self.resource_span.clone(),
490             "Semaphore::acquire_many_owned",
491             "poll",
492             true,
493         );
494         #[cfg(not(all(tokio_unstable, feature = "tracing")))]
495         let inner = self.ll_sem.acquire(n);
496 
497         inner.await?;
498         Ok(OwnedSemaphorePermit {
499             sem: self,
500             permits: n,
501         })
502     }
503 
504     /// Tries to acquire a permit from the semaphore.
505     ///
506     /// The semaphore must be wrapped in an [`Arc`] to call this method. If
507     /// the semaphore has been closed, this returns a [`TryAcquireError::Closed`]
508     /// and a [`TryAcquireError::NoPermits`] if there are no permits left.
509     /// Otherwise, this returns a [`OwnedSemaphorePermit`] representing the
510     /// acquired permit.
511     ///
512     /// # Examples
513     ///
514     /// ```
515     /// use std::sync::Arc;
516     /// use tokio::sync::{Semaphore, TryAcquireError};
517     ///
518     /// # fn main() {
519     /// let semaphore = Arc::new(Semaphore::new(2));
520     ///
521     /// let permit_1 = Arc::clone(&semaphore).try_acquire_owned().unwrap();
522     /// assert_eq!(semaphore.available_permits(), 1);
523     ///
524     /// let permit_2 = Arc::clone(&semaphore).try_acquire_owned().unwrap();
525     /// assert_eq!(semaphore.available_permits(), 0);
526     ///
527     /// let permit_3 = semaphore.try_acquire_owned();
528     /// assert_eq!(permit_3.err(), Some(TryAcquireError::NoPermits));
529     /// # }
530     /// ```
531     ///
532     /// [`Arc`]: std::sync::Arc
533     /// [`TryAcquireError::Closed`]: crate::sync::TryAcquireError::Closed
534     /// [`TryAcquireError::NoPermits`]: crate::sync::TryAcquireError::NoPermits
535     /// [`OwnedSemaphorePermit`]: crate::sync::OwnedSemaphorePermit
try_acquire_owned(self: Arc<Self>) -> Result<OwnedSemaphorePermit, TryAcquireError>536     pub fn try_acquire_owned(self: Arc<Self>) -> Result<OwnedSemaphorePermit, TryAcquireError> {
537         match self.ll_sem.try_acquire(1) {
538             Ok(_) => Ok(OwnedSemaphorePermit {
539                 sem: self,
540                 permits: 1,
541             }),
542             Err(e) => Err(e),
543         }
544     }
545 
546     /// Tries to acquire `n` permits from the semaphore.
547     ///
548     /// The semaphore must be wrapped in an [`Arc`] to call this method. If
549     /// the semaphore has been closed, this returns a [`TryAcquireError::Closed`]
550     /// and a [`TryAcquireError::NoPermits`] if there are no permits left.
551     /// Otherwise, this returns a [`OwnedSemaphorePermit`] representing the
552     /// acquired permit.
553     ///
554     /// # Examples
555     ///
556     /// ```
557     /// use std::sync::Arc;
558     /// use tokio::sync::{Semaphore, TryAcquireError};
559     ///
560     /// # fn main() {
561     /// let semaphore = Arc::new(Semaphore::new(4));
562     ///
563     /// let permit_1 = Arc::clone(&semaphore).try_acquire_many_owned(3).unwrap();
564     /// assert_eq!(semaphore.available_permits(), 1);
565     ///
566     /// let permit_2 = semaphore.try_acquire_many_owned(2);
567     /// assert_eq!(permit_2.err(), Some(TryAcquireError::NoPermits));
568     /// # }
569     /// ```
570     ///
571     /// [`Arc`]: std::sync::Arc
572     /// [`TryAcquireError::Closed`]: crate::sync::TryAcquireError::Closed
573     /// [`TryAcquireError::NoPermits`]: crate::sync::TryAcquireError::NoPermits
574     /// [`OwnedSemaphorePermit`]: crate::sync::OwnedSemaphorePermit
try_acquire_many_owned( self: Arc<Self>, n: u32, ) -> Result<OwnedSemaphorePermit, TryAcquireError>575     pub fn try_acquire_many_owned(
576         self: Arc<Self>,
577         n: u32,
578     ) -> Result<OwnedSemaphorePermit, TryAcquireError> {
579         match self.ll_sem.try_acquire(n) {
580             Ok(_) => Ok(OwnedSemaphorePermit {
581                 sem: self,
582                 permits: n,
583             }),
584             Err(e) => Err(e),
585         }
586     }
587 
588     /// Closes the semaphore.
589     ///
590     /// This prevents the semaphore from issuing new permits and notifies all pending waiters.
591     ///
592     /// # Examples
593     ///
594     /// ```
595     /// use tokio::sync::Semaphore;
596     /// use std::sync::Arc;
597     /// use tokio::sync::TryAcquireError;
598     ///
599     /// #[tokio::main]
600     /// async fn main() {
601     ///     let semaphore = Arc::new(Semaphore::new(1));
602     ///     let semaphore2 = semaphore.clone();
603     ///
604     ///     tokio::spawn(async move {
605     ///         let permit = semaphore.acquire_many(2).await;
606     ///         assert!(permit.is_err());
607     ///         println!("waiter received error");
608     ///     });
609     ///
610     ///     println!("closing semaphore");
611     ///     semaphore2.close();
612     ///
613     ///     // Cannot obtain more permits
614     ///     assert_eq!(semaphore2.try_acquire().err(), Some(TryAcquireError::Closed))
615     /// }
616     /// ```
close(&self)617     pub fn close(&self) {
618         self.ll_sem.close();
619     }
620 
621     /// Returns true if the semaphore is closed
is_closed(&self) -> bool622     pub fn is_closed(&self) -> bool {
623         self.ll_sem.is_closed()
624     }
625 }
626 
627 impl<'a> SemaphorePermit<'a> {
628     /// Forgets the permit **without** releasing it back to the semaphore.
629     /// This can be used to reduce the amount of permits available from a
630     /// semaphore.
forget(mut self)631     pub fn forget(mut self) {
632         self.permits = 0;
633     }
634 
635     /// Merge two [`SemaphorePermit`] instances together, consuming `other`
636     /// without releasing the permits it holds.
637     ///
638     /// Permits held by both `self` and `other` are released when `self` drops.
639     ///
640     /// # Panics
641     ///
642     /// This function panics if permits from different [`Semaphore`] instances
643     /// are merged.
644     #[track_caller]
merge(&mut self, mut other: Self)645     pub fn merge(&mut self, mut other: Self) {
646         assert!(
647             std::ptr::eq(self.sem, other.sem),
648             "merging permits from different semaphore instances"
649         );
650         self.permits += other.permits;
651         other.permits = 0;
652     }
653 }
654 
655 impl OwnedSemaphorePermit {
656     /// Forgets the permit **without** releasing it back to the semaphore.
657     /// This can be used to reduce the amount of permits available from a
658     /// semaphore.
forget(mut self)659     pub fn forget(mut self) {
660         self.permits = 0;
661     }
662 
663     /// Merge two [`OwnedSemaphorePermit`] instances together, consuming `other`
664     /// without releasing the permits it holds.
665     ///
666     /// Permits held by both `self` and `other` are released when `self` drops.
667     ///
668     /// # Panics
669     ///
670     /// This function panics if permits from different [`Semaphore`] instances
671     /// are merged.
672     #[track_caller]
merge(&mut self, mut other: Self)673     pub fn merge(&mut self, mut other: Self) {
674         assert!(
675             Arc::ptr_eq(&self.sem, &other.sem),
676             "merging permits from different semaphore instances"
677         );
678         self.permits += other.permits;
679         other.permits = 0;
680     }
681 
682     /// Returns the [`Semaphore`] from which this permit was acquired.
semaphore(&self) -> &Arc<Semaphore>683     pub fn semaphore(&self) -> &Arc<Semaphore> {
684         &self.sem
685     }
686 }
687 
688 impl Drop for SemaphorePermit<'_> {
drop(&mut self)689     fn drop(&mut self) {
690         self.sem.add_permits(self.permits as usize);
691     }
692 }
693 
694 impl Drop for OwnedSemaphorePermit {
drop(&mut self)695     fn drop(&mut self) {
696         self.sem.add_permits(self.permits as usize);
697     }
698 }
699