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

doc: Add examples to Semaphore #3808

Merged
merged 10 commits into from Jun 11, 2021
228 changes: 228 additions & 0 deletions tokio/src/sync/semaphore.rs
Expand Up @@ -24,6 +24,51 @@ use std::sync::Arc;
/// To use the `Semaphore` in a poll function, you can use the [`PollSemaphore`]
/// utility.
///
/// # Examples
///
/// ```
/// use std::sync::Arc;
/// use tokio::sync::{Semaphore, TryAcquireError};
///
/// #[tokio::main]
/// async fn main() {
/// let semaphore = Semaphore::new(3);
/// {
oguzbilgener marked this conversation as resolved.
Show resolved Hide resolved
/// let a_permit = semaphore.acquire().await;
/// let two_permits = semaphore.acquire_many(2).await;
/// assert_eq!(a_permit.is_ok(), true);
/// assert_eq!(two_permits.is_ok(), true);
/// // all three permits acquired without waiting
/// assert_eq!(semaphore.available_permits(), 0);
/// // any more `acquire()` or `acquire_many()` calls will wait
/// // `try_acquire` attempts to acquire, but fail immediately in this case
/// let fourth_permit = semaphore.try_acquire();
/// assert_eq!(fourth_permit.err(), Some(TryAcquireError::NoPermits));
/// semaphore.close();
/// // cannot obtain more permits after close
/// assert_eq!(semaphore.acquire().await.is_err(), true);
/// } // all permits are dropped at this point
/// assert_eq!(semaphore.available_permits(), 3);
oguzbilgener marked this conversation as resolved.
Show resolved Hide resolved
///
/// // wrap a semaphore in [`Arc`] to share a semaphore across tasks
/// // use [`acquire_owned`] to move permits across tasks
/// let semaphore = Arc::new(Semaphore::new(3));
/// let mut join_handles = Vec::new();
/// for _ in 1..=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);
/// }));
/// }
/// assert_eq!(join_handles.len(), 5);
/// for j in join_handles {
/// j.await.unwrap();
/// }
/// }
/// ```
///
/// [`PollSemaphore`]: https://docs.rs/tokio-util/0.6/tokio_util/sync/struct.PollSemaphore.html
#[derive(Debug)]
pub struct Semaphore {
Expand Down Expand Up @@ -105,6 +150,25 @@ impl Semaphore {
/// Otherwise, this returns a [`SemaphorePermit`] representing the
/// acquired permit.
///
/// # Examples
///
///```
oguzbilgener marked this conversation as resolved.
Show resolved Hide resolved
/// use tokio::sync::Semaphore;
///
/// #[tokio::main]
/// async fn main() {
/// let semaphore = Semaphore::new(2);
/// let p1 = semaphore.acquire().await;
/// let p2 = semaphore.acquire().await;
/// assert_eq!(p1.is_ok(), true);
/// assert_eq!(p2.is_ok(), true);
/// assert_eq!(semaphore.available_permits(), 0);
/// semaphore.close();
/// let p3 = semaphore.acquire().await;
/// assert_eq!(p3.is_err(), true);
oguzbilgener marked this conversation as resolved.
Show resolved Hide resolved
/// }
/// ```
///
/// [`AcquireError`]: crate::sync::AcquireError
/// [`SemaphorePermit`]: crate::sync::SemaphorePermit
pub async fn acquire(&self) -> Result<SemaphorePermit<'_>, AcquireError> {
Expand All @@ -121,6 +185,25 @@ impl Semaphore {
/// Otherwise, this returns a [`SemaphorePermit`] representing the
/// acquired permits.
///
/// # Examples
///
///```
oguzbilgener marked this conversation as resolved.
Show resolved Hide resolved
/// use tokio::sync::Semaphore;
///
/// #[tokio::main]
/// async fn main() {
/// let semaphore = Semaphore::new(5);
/// let p1 = semaphore.acquire_many(3).await;
/// assert_eq!(semaphore.available_permits(), 2);
/// let p2 = semaphore.acquire_many(2).await;
/// assert_eq!(p1.is_ok(), true);
/// assert_eq!(p2.is_ok(), true);
/// semaphore.close();
/// let p3 = semaphore.acquire_many(99).await;
/// assert_eq!(p3.is_err(), true);
/// }
/// ```
///
/// [`AcquireError`]: crate::sync::AcquireError
/// [`SemaphorePermit`]: crate::sync::SemaphorePermit
pub async fn acquire_many(&self, n: u32) -> Result<SemaphorePermit<'_>, AcquireError> {
Expand All @@ -137,6 +220,26 @@ impl Semaphore {
/// and a [`TryAcquireError::NoPermits`] if there are no permits left. Otherwise,
/// this returns a [`SemaphorePermit`] representing the acquired permits.
///
/// # Examples
///
///```
oguzbilgener marked this conversation as resolved.
Show resolved Hide resolved
/// use tokio::sync::{Semaphore, TryAcquireError};
///
/// #[tokio::main]
/// async fn main() {
/// let semaphore = Semaphore::new(2);
/// let p1 = semaphore.acquire().await;
/// let p2 = semaphore.try_acquire();
/// let p3 = semaphore.try_acquire();
/// assert_eq!(p1.is_ok(), true);
/// assert_eq!(p2.is_ok(), true);
/// assert_eq!(p3.err(), Some(TryAcquireError::NoPermits));
/// semaphore.close();
/// let p4 = semaphore.try_acquire();
/// assert_eq!(p4.err(), Some(TryAcquireError::Closed));
/// }
/// ```
///
/// [`TryAcquireError::Closed`]: crate::sync::TryAcquireError::Closed
/// [`TryAcquireError::NoPermits`]: crate::sync::TryAcquireError::NoPermits
/// [`SemaphorePermit`]: crate::sync::SemaphorePermit
Expand All @@ -156,6 +259,25 @@ impl Semaphore {
/// and a [`TryAcquireError::NoPermits`] if there are no permits left. Otherwise,
/// this returns a [`SemaphorePermit`] representing the acquired permits.
oguzbilgener marked this conversation as resolved.
Show resolved Hide resolved
///
/// # Examples
///
///```
oguzbilgener marked this conversation as resolved.
Show resolved Hide resolved
/// use tokio::sync::{Semaphore, TryAcquireError};
///
/// #[tokio::main]
/// async fn main() {
/// let semaphore = Semaphore::new(4);
/// let p1 = semaphore.try_acquire_many(3);
/// assert_eq!(semaphore.available_permits(), 1);
/// let p2 = semaphore.try_acquire_many(2);
/// assert_eq!(p1.is_ok(), true);
/// assert_eq!(p2.err(), Some(TryAcquireError::NoPermits));
/// semaphore.close();
/// let p3 = semaphore.try_acquire_many(99);
/// assert_eq!(p3.err(), Some(TryAcquireError::Closed));
/// }
/// ```
///
/// [`TryAcquireError::Closed`]: crate::sync::TryAcquireError::Closed
/// [`TryAcquireError::NoPermits`]: crate::sync::TryAcquireError::NoPermits
/// [`SemaphorePermit`]: crate::sync::SemaphorePermit
Expand All @@ -176,6 +298,32 @@ impl Semaphore {
/// Otherwise, this returns a [`OwnedSemaphorePermit`] representing the
/// acquired permit.
///
/// # Examples
///
/// ```
/// use std::sync::Arc;
/// use tokio::sync::Semaphore;
///
/// #[tokio::main]
/// async fn main() {
/// let semaphore = Arc::new(Semaphore::new(2));
/// let sem_clone = semaphore.clone();
/// let handle = tokio::spawn(async move {
/// let permit = sem_clone.acquire_owned().await;
/// assert_eq!(permit.is_ok(), true);
/// });
/// {
/// let p1 = semaphore.clone().acquire_owned().await;
/// assert_eq!(semaphore.available_permits(), 1);
/// let p2 = semaphore.clone().acquire_owned().await;
/// assert_eq!(semaphore.available_permits(), 0);
/// assert_eq!(p1.is_ok(), true);
/// assert_eq!(p2.is_ok(), true);
/// } // release the permits so the task can acquire them
/// handle.await.unwrap();
oguzbilgener marked this conversation as resolved.
Show resolved Hide resolved
/// }
/// ```
///
/// [`Arc`]: std::sync::Arc
/// [`AcquireError`]: crate::sync::AcquireError
/// [`OwnedSemaphorePermit`]: crate::sync::OwnedSemaphorePermit
Expand All @@ -194,6 +342,33 @@ impl Semaphore {
/// Otherwise, this returns a [`OwnedSemaphorePermit`] representing the
/// acquired permit.
///
/// # Examples
///
/// ```
/// use std::sync::Arc;
/// use tokio::sync::Semaphore;
///
/// #[tokio::main]
/// async fn main() {
/// let semaphore = Arc::new(Semaphore::new(5));
/// let sem_clone = semaphore.clone();
/// let handle = tokio::spawn(async move {
/// let permit = sem_clone.acquire_many_owned(5).await;
/// assert_eq!(permit.is_ok(), true);
/// });
/// {
/// let p1 = semaphore.clone().acquire_many_owned(2).await;
/// assert_eq!(semaphore.available_permits(), 3);
/// let p2 = semaphore.clone().acquire_owned().await;
/// assert_eq!(semaphore.available_permits(), 2);
/// assert_eq!(p1.is_ok(), true);
/// assert_eq!(p2.is_ok(), true);
/// } // release the permits so the task can acquire them
/// handle.await.unwrap();
/// }
/// ```
///
///
oguzbilgener marked this conversation as resolved.
Show resolved Hide resolved
/// [`Arc`]: std::sync::Arc
/// [`AcquireError`]: crate::sync::AcquireError
/// [`OwnedSemaphorePermit`]: crate::sync::OwnedSemaphorePermit
Expand All @@ -216,6 +391,34 @@ impl Semaphore {
/// Otherwise, this returns a [`OwnedSemaphorePermit`] representing the
/// acquired permit.
///
/// # Examples
///
/// ```
/// use std::sync::Arc;
/// use tokio::sync::{Semaphore, TryAcquireError};
///
/// #[tokio::main]
/// async fn main() {
/// let semaphore = Arc::new(Semaphore::new(2));
/// let sem_clone = semaphore.clone();
/// let handle = tokio::spawn(async move {
/// let permit = sem_clone.try_acquire_owned();
/// assert_eq!(permit.is_ok(), true);
/// });
/// {
/// let p1 = semaphore.clone().try_acquire_owned();
/// assert_eq!(semaphore.available_permits(), 1);
/// let p2 = semaphore.clone().try_acquire_owned();
/// assert_eq!(semaphore.available_permits(), 0);
/// let p3 = semaphore.clone().try_acquire_owned();
/// assert_eq!(p1.is_ok(), true);
/// assert_eq!(p2.is_ok(), true);
/// assert_eq!(p3.err(), Some(TryAcquireError::NoPermits));
/// } // release the permits so the task can acquire them
/// handle.await.unwrap();
/// }
/// ```
///
/// [`Arc`]: std::sync::Arc
/// [`TryAcquireError::Closed`]: crate::sync::TryAcquireError::Closed
/// [`TryAcquireError::NoPermits`]: crate::sync::TryAcquireError::NoPermits
Expand All @@ -238,6 +441,31 @@ impl Semaphore {
/// Otherwise, this returns a [`OwnedSemaphorePermit`] representing the
/// acquired permit.
///
/// # Examples
///
/// ```
/// use std::sync::Arc;
/// use tokio::sync::{Semaphore, TryAcquireError};
///
/// #[tokio::main]
/// async fn main() {
/// let semaphore = Arc::new(Semaphore::new(5));
/// let sem_clone = semaphore.clone();
/// let handle = tokio::spawn(async move {
/// let permit = sem_clone.try_acquire_many_owned(5);
/// assert_eq!(permit.is_ok(), true);
/// });
/// {
/// let p1 = semaphore.clone().try_acquire_many_owned(3);
/// assert_eq!(semaphore.available_permits(), 2);
/// let p2 = semaphore.clone().try_acquire_many_owned(99);
/// assert_eq!(p1.is_ok(), true);
/// assert_eq!(p2.err(), Some(TryAcquireError::NoPermits));
/// } // release the permits so the task can acquire them
/// handle.await.unwrap();
/// }
/// ```
///
/// [`Arc`]: std::sync::Arc
/// [`TryAcquireError::Closed`]: crate::sync::TryAcquireError::Closed
/// [`TryAcquireError::NoPermits`]: crate::sync::TryAcquireError::NoPermits
Expand Down