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