Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Semaphore example using an Arc<Semaphore> for semaphore passing #5956

Merged
merged 33 commits into from Sep 19, 2023
Merged
Changes from 21 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
f658611
Semaphore example using an Arc<Semaphore> for semaphore passing
alexanderkirilin Aug 27, 2023
08912f7
Merge remote-tracking branch 'origin/master' into semaphore-example-file
alexanderkirilin Aug 28, 2023
eef8f07
Update
alexanderkirilin Aug 28, 2023
2f9d830
Fix example
alexanderkirilin Aug 28, 2023
9bc830e
Fix example
alexanderkirilin Aug 28, 2023
2805755
Fix example
alexanderkirilin Aug 28, 2023
c7151c7
Update tokio/src/sync/semaphore.rs
alexanderkirilin Aug 29, 2023
912e928
Merge branch 'master' into semaphore-example-file
alexanderkirilin Aug 29, 2023
0914b0f
Change example to actual request limiter
alexanderkirilin Aug 29, 2023
7428441
Swap loop to get around CI
alexanderkirilin Aug 29, 2023
0123816
No run docstring
alexanderkirilin Aug 29, 2023
b17bddc
Add comment
alexanderkirilin Aug 29, 2023
1a7a25b
Update tokio/src/sync/semaphore.rs
alexanderkirilin Aug 29, 2023
a60ff46
Merge remote-tracking branch 'origin/semaphore-example-file' into sem…
alexanderkirilin Aug 29, 2023
bd20813
Update
alexanderkirilin Aug 29, 2023
a8bb79d
Update
alexanderkirilin Aug 29, 2023
d605549
Update
alexanderkirilin Aug 29, 2023
ae49b96
Update tokio/src/sync/semaphore.rs
alexanderkirilin Aug 31, 2023
77d465b
Update
alexanderkirilin Aug 31, 2023
8de8bef
Update
alexanderkirilin Aug 31, 2023
8fd7a16
Update
alexanderkirilin Aug 31, 2023
b92d933
Update tokio/src/sync/semaphore.rs
alexanderkirilin Sep 1, 2023
cf4f6fb
Update tokio/src/sync/semaphore.rs
alexanderkirilin Sep 1, 2023
87af825
Update tokio/src/sync/semaphore.rs
alexanderkirilin Sep 1, 2023
05a2900
Update tokio/src/sync/semaphore.rs
alexanderkirilin Sep 2, 2023
f8afd1f
Update tokio/src/sync/semaphore.rs
alexanderkirilin Sep 2, 2023
b4790c4
Update
alexanderkirilin Sep 2, 2023
b364ca8
Update tokio/src/sync/semaphore.rs
alexanderkirilin Sep 6, 2023
9180840
Update tokio/src/sync/semaphore.rs
alexanderkirilin Sep 6, 2023
e18f86c
Update tokio/src/sync/semaphore.rs
alexanderkirilin Sep 6, 2023
7a94754
Merge branch 'master' into semaphore-example-file
alexanderkirilin Sep 6, 2023
1158412
Update
alexanderkirilin Sep 6, 2023
bc2079d
Merge remote-tracking branch 'origin/master' into semaphore-example-file
alexanderkirilin Sep 18, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
74 changes: 48 additions & 26 deletions tokio/src/sync/semaphore.rs
Expand Up @@ -47,32 +47,6 @@ use std::sync::Arc;
/// }
/// ```
///
/// Use [`Semaphore::acquire_owned`] to move permits across tasks:
///
/// ```
/// use std::sync::Arc;
/// use tokio::sync::Semaphore;
///
/// #[tokio::main]
/// async fn main() {
/// let semaphore = Arc::new(Semaphore::new(3));
/// let mut join_handles = Vec::new();
///
/// for _ in 0..5 {
/// let permit = semaphore.clone().acquire_owned().await.unwrap();
/// join_handles.push(tokio::spawn(async move {
/// // perform task...
/// // explicitly own `permit` in the task
/// drop(permit);
/// }));
/// }
///
/// for handle in join_handles {
/// handle.await.unwrap();
/// }
/// }
/// ```
///
/// Limit the number of simultaneously opened files in your program.
///
/// Most operating systems have limits on the number of open file
Expand Down Expand Up @@ -102,6 +76,54 @@ 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.
///
/// However, in contrast to the file example, this example uses an `Arc<Semaphore>`.
alexanderkirilin marked this conversation as resolved.
Show resolved Hide resolved
/// Before we spawn a new task to process a request, we must acquire a permit from
/// this semaphore, in order to limit usage of system resources (like file descriptors,
/// memory usage, CPU time, etc.). Once acquired, a new task is spawned; and once
alexanderkirilin marked this conversation as resolved.
Show resolved Hide resolved
/// finished, the permit is dropped inside of the task to allow others to spawn.
/// Permits must be acquired via [`Semaphore::acquire_owned`], in order to be
/// movable across the task boundary. Contrastingly, if the semaphore were a global,
alexanderkirilin marked this conversation as resolved.
Show resolved Hide resolved
/// as in the file-limiting example, only ['Semaphore::acquire'] would be necessary.
/// This is because a `Permit<'static>` would be returned, which is movable across
/// task boundaries, since the semaphore lives forever.
alexanderkirilin marked this conversation as resolved.
Show resolved Hide resolved
///
/// ```no_run
/// use std::sync::Arc;
/// use tokio::sync::Semaphore;
/// use tokio::net::{TcpListener, TcpStream};
alexanderkirilin marked this conversation as resolved.
Show resolved Hide resolved
///
/// #[tokio::main]
/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
alexanderkirilin marked this conversation as resolved.
Show resolved Hide resolved
/// let semaphore = Arc::new(Semaphore::new(3));
/// let listener = TcpListener::bind("127.0.0.1:8080").await?;
///
/// loop {
/// // Acquire permit before accepting, to avoid needlessly taking up a (finite) file descriptor
alexanderkirilin marked this conversation as resolved.
Show resolved Hide resolved
/// 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 TcpStream) {
/// # // Do work
/// # }
alexanderkirilin marked this conversation as resolved.
Show resolved Hide resolved
/// ```
///
/// [`PollSemaphore`]: https://docs.rs/tokio-util/latest/tokio_util/sync/struct.PollSemaphore.html
/// [`Semaphore::acquire_owned`]: crate::sync::Semaphore::acquire_owned
#[derive(Debug)]
Expand Down