mirror of
https://github.com/tokio-rs/tokio.git
synced 2026-08-21 00:00:10 +02:00
sync: reorder Semaphore examples (#6031)
This commit is contained in:
+49
-49
@@ -47,7 +47,7 @@ use std::sync::Arc;
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// Limit the number of simultaneously opened files in your program.
|
||||
/// ## Limit the number of simultaneously opened files in your program.
|
||||
///
|
||||
/// Most operating systems have limits on the number of open file
|
||||
/// handles. Even in systems without explicit limits, resource constraints
|
||||
@@ -76,7 +76,54 @@ use std::sync::Arc;
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// Implement a simple token bucket for rate limiting
|
||||
/// ## 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));
|
||||
/// let listener = TcpListener::bind("127.0.0.1:8080").await?;
|
||||
///
|
||||
/// loop {
|
||||
/// // Acquire permit before accepting the next socket.
|
||||
/// //
|
||||
/// // We use `acquire_owned` so that we can move `permit` into
|
||||
/// // other tasks.
|
||||
/// let permit = semaphore.clone().acquire_owned().await.unwrap();
|
||||
/// let (mut socket, _) = listener.accept().await?;
|
||||
///
|
||||
/// tokio::spawn(async move {
|
||||
/// // Do work using the socket.
|
||||
/// handle_connection(&mut socket).await;
|
||||
/// // Drop socket while the permit is still live.
|
||||
/// drop(socket);
|
||||
/// // Drop the permit, so more tasks can be created.
|
||||
/// drop(permit);
|
||||
/// });
|
||||
/// }
|
||||
/// }
|
||||
/// # async fn handle_connection(_socket: &mut tokio::net::TcpStream) {
|
||||
/// # // Do work
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// ## Rate limiting using a token bucket
|
||||
///
|
||||
/// Many applications and systems have constraints on the rate at which certain
|
||||
/// operations should occur. Exceeding this rate can result in suboptimal
|
||||
@@ -159,53 +206,6 @@ use std::sync::Arc;
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// 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));
|
||||
/// let listener = TcpListener::bind("127.0.0.1:8080").await?;
|
||||
///
|
||||
/// loop {
|
||||
/// // Acquire permit before accepting the next socket.
|
||||
/// //
|
||||
/// // We use `acquire_owned` so that we can move `permit` into
|
||||
/// // other tasks.
|
||||
/// let permit = semaphore.clone().acquire_owned().await.unwrap();
|
||||
/// let (mut socket, _) = listener.accept().await?;
|
||||
///
|
||||
/// tokio::spawn(async move {
|
||||
/// // Do work using the socket.
|
||||
/// handle_connection(&mut socket).await;
|
||||
/// // Drop socket while the permit is still live.
|
||||
/// drop(socket);
|
||||
/// // Drop the permit, so more tasks can be created.
|
||||
/// drop(permit);
|
||||
/// });
|
||||
/// }
|
||||
/// }
|
||||
/// # async fn handle_connection(_socket: &mut tokio::net::TcpStream) {
|
||||
/// # // Do work
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// [`PollSemaphore`]: https://docs.rs/tokio-util/latest/tokio_util/sync/struct.PollSemaphore.html
|
||||
/// [`Semaphore::acquire_owned`]: crate::sync::Semaphore::acquire_owned
|
||||
#[derive(Debug)]
|
||||
|
||||
Reference in New Issue
Block a user