Repository: tokio-rs/tokio
File: tokio/src/sync/semaphore.rs (Rust)

Code before:
///             let sem = sem.clone();
///             let mut interval = interval(duration);
///             interval.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip);
///
///             async move {
///                 loop {
///                     interval.tick().await;
///
///                     let cap = rate - sem.available_permits();
///                     sem.add_permits(cap.min(1));
///                 }
///             }
///         });
///
///         Self { jh, sem }
///     }
///
///     async fn acquire(&self) -> Result<(), AcquireError> {
///         self.sem.acquire().await.map(|p| p.forget())
///     }
///
///     async fn close(self) {
///         self.jh.abort();
///         let _ = self.jh.await;
///
///         self.sem.close();
///     }
/// }
///
/// #[tokio::main]
/// async fn main() {
///     let ops = 1.0; // operation per second
///     let update_interval = 1.0 / ops;
///     let bucket = TokenBucket::new(Duration::from_secs_f32(update_interval));
///
///     for _ in 0..5 {
///         bucket.acquire().await.unwrap();
///
///         // do the operation
///     }
///
///     bucket.close().await;
/// }
/// ```
///
/// [`PollSemaphore`]: https://docs.rs/tokio-util/latest/tokio_util/sync/struct.PollSemaphore.html
/// [`Semaphore::acquire_owned`]: crate::sync::Semaphore::acquire_owned
#[derive(Debug)]
pub struct Semaphore {
    /// The low level semaphore
    ll_sem: ll::Semaphore,

Review comment (suggestion):
```suggestion
///         self.sem.close();
///         self.jh.abort();
///         let _ = self.jh.await;
```

Code after:
///     }
///
///     async fn acquire(&self) -> Result<(), AcquireError> {
///         self.sem.acquire().await.map(|p| p.forget())
///     }
///
///     async fn close(self) {
///         self.sem.close();
///         self.jh.abort();
///         let _ = self.jh.await;
///     }
/// }
///
/// #[tokio::main]
/// async fn main() {
///     let capacity = 5; // operation per second
///     let update_interval = Duration::from_secs_f32(1.0 / capacity as f32);
///     let bucket = TokenBucket::new(update_interval, capacity);
///
///     for _ in 0..5 {
///         bucket.acquire().await.unwrap();
///
///         // do the operation
///     }
///
///     bucket.close().await;
/// }
/// ```
///
/// Limit the number of incoming requests being handled at the same time.
///
/// Similar to limiting the number of simultaneously opened files, network handles
/// are a limited resource. Allowing an unbounded amount of requests to be processed
/// could result in a denial-of-service, among many other issues.
///
/// This example uses an `Arc<Semaphore>` instead of a global variable.
/// To limit the number of requests that can be processed at the time,
/// we acquire a permit for each task before spawning it. Once acquired,
/// a new task is spawned; and once finished, the permit is dropped inside
/// of the task to allow others to spawn. Permits must be acquired via
/// [`Semaphore::acquire_owned`] to be movable across the task boundary.
/// (Since our semaphore is not a global variable — if it was, then `acquire` would be enough.)
///
/// ```no_run
/// use std::sync::Arc;
/// use tokio::sync::Semaphore;
/// use tokio::net::TcpListener;
///
/// #[tokio::main]
/// async fn main() -> std::io::Result<()> {
///     let semaphore = Arc::new(Semaphore::new(3));