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