1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
use std::{mem, fmt}; use crate::Semaphore; use std::sync::Arc; use std::thread::panicking; use std::fmt::{Debug, Formatter}; /// A guard returned by [`Semaphore::acquire`] that will call [`Semaphore::release`] when it /// is dropped (falls out of scope). /// # Examples /// ``` /// # use futures::executor::block_on; /// use async_weighted_semaphore::{Semaphore, SemaphoreGuard}; /// # block_on(async{ /// let semaphore = Semaphore::new(1); /// let guard: SemaphoreGuard = semaphore.acquire(1).await.unwrap(); /// # }) /// ``` #[must_use] pub struct SemaphoreGuard<'a> { semaphore: &'a Semaphore, amount: usize, panicking: bool, } /// A guard returned by [`Semaphore::acquire_arc`] that will call [`Semaphore::release`] when it /// is dropped (falls out of scope). Can be sent between threads. #[must_use] pub struct SemaphoreGuardArc { semaphore: Option<Arc<Semaphore>>, amount: usize, panicking: bool, } impl<'a> SemaphoreGuard<'a> { pub fn new(semaphore: &'a Semaphore, amount: usize) -> Self { SemaphoreGuard { semaphore, amount, panicking: panicking() } } /// Drop the guard without calling [`Semaphore::release`]. This is useful when `release`s don't /// correspond one-to-one with `acquires` or it's difficult to send the guard to the releaser. /// # Examples /// ``` /// # use async_weighted_semaphore::{Semaphore, PoisonError, SemaphoreGuardArc}; /// use async_channel::{Sender, SendError}; /// // Limit size of a producer-consumer queue. Receivers may wait for any number of items /// // to be available. /// async fn send<T>(semaphore: &Semaphore, /// sender: &Sender<T>, /// message: T /// ) -> Result<(), SendError<T>>{ /// match semaphore.acquire(1).await { /// // A semaphore can be poisoned to prevent deadlock when a channel closes. /// Err(PoisonError) => Err(SendError(message)), /// Ok(guard) => { /// sender.send(message).await?; /// guard.forget(); /// Ok(()) /// } /// } /// } /// ``` pub fn forget(self) -> usize { let amount = self.amount; mem::forget(self); amount } } impl SemaphoreGuardArc { pub fn new(semaphore: Arc<Semaphore>, amount: usize) -> Self { SemaphoreGuardArc { semaphore: Some(semaphore), amount, panicking: panicking() } } /// Drop the guard without calling [`Semaphore::release`]. This is useful when `release`s don't /// correspond one-to-one with `acquires` or it's difficult to send the guard to the releaser. /// # Examples /// ``` /// # use async_weighted_semaphore::{Semaphore, PoisonError, SemaphoreGuardArc}; /// # use std::sync::Arc; /// use async_channel::{Sender, SendError}; /// // Limit size of a producer-consumer queue. Receivers may wait for any number of items /// // to be available. /// async fn send<T>(semaphore: &Arc<Semaphore>, /// sender: &Sender<T>, /// message: T /// ) -> Result<(), SendError<T>>{ /// match semaphore.acquire_arc(1).await { /// // A semaphore can be poisoned to prevent deadlock when a channel closes. /// Err(PoisonError) => Err(SendError(message)), /// Ok(guard) => { /// sender.send(message).await?; /// guard.forget(); /// Ok(()) /// } /// } /// } /// ``` pub fn forget(mut self) -> usize { self.semaphore = None; let amount = self.amount; mem::forget(self); amount } } impl<'a> Drop for SemaphoreGuard<'a> { fn drop(&mut self) { if !self.panicking && panicking() { self.semaphore.poison(); } else { self.semaphore.release(self.amount); } } } impl Drop for SemaphoreGuardArc { fn drop(&mut self) { if let Some(semaphore) = self.semaphore.take() { if !self.panicking && panicking() { semaphore.poison(); } else { semaphore.release(self.amount); } } } } impl<'a> Debug for SemaphoreGuard<'a> { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { write!(f, "SemaphoreGuard({})", self.amount) } } impl Debug for SemaphoreGuardArc { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { write!(f, "SemaphoreGuardArc({})", self.amount) } }