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