Semaphore

Struct Semaphore 

Source
pub struct Semaphore { /* private fields */ }
Expand description

A tracked semaphore that automatically records acquisition metrics and integrates with deadlock detection.

This is a drop-in replacement for tokio::sync::Semaphore with additional observability features.

§Example

use async_inspect::sync::Semaphore;

#[tokio::main]
async fn main() {
    // Allow up to 3 concurrent operations
    let semaphore = Semaphore::new(3, "connection_pool");
    let semaphore = std::sync::Arc::new(semaphore);

    let mut handles = vec![];

    for i in 0..10 {
        let sem = semaphore.clone();
        handles.push(tokio::spawn(async move {
            let _permit = sem.acquire().await.unwrap();
            println!("Task {} acquired permit", i);
            tokio::time::sleep(std::time::Duration::from_millis(100)).await;
        }));
    }

    for h in handles {
        h.await.unwrap();
    }

    // Check acquisition metrics
    let metrics = semaphore.metrics();
    println!("Total acquisitions: {}", metrics.acquisitions);
    println!("Contentions: {}", metrics.contentions);
}

Implementations§

Source§

impl Semaphore

Source

pub fn new(permits: usize, name: impl Into<String>) -> Self

Create a new tracked semaphore with the given number of permits.

§Arguments
  • permits - The number of permits available
  • name - A descriptive name for debugging and metrics
§Example
use async_inspect::sync::Semaphore;

// Create a semaphore limiting to 5 concurrent operations
let semaphore = Semaphore::new(5, "rate_limiter");
Source

pub async fn acquire(&self) -> Result<SemaphorePermit<'_>, AcquireError>

Acquire a permit, blocking until one is available.

§Returns

Returns Ok(SemaphorePermit) if a permit was acquired, or Err(AcquireError) if the semaphore was closed.

§Example
use async_inspect::sync::Semaphore;

let semaphore = Semaphore::new(3, "pool");
let permit = semaphore.acquire().await.unwrap();
// ... use the resource ...
drop(permit); // Release the permit
Source

pub async fn acquire_many( &self, n: u32, ) -> Result<SemaphorePermit<'_>, AcquireError>

Acquire multiple permits at once.

§Arguments
  • n - Number of permits to acquire
§Example
use async_inspect::sync::Semaphore;

let semaphore = Semaphore::new(10, "batch_pool");
let permit = semaphore.acquire_many(5).await.unwrap();
// ... use 5 resources at once ...
Source

pub fn try_acquire(&self) -> Result<SemaphorePermit<'_>, TryAcquireError>

Try to acquire a permit immediately.

Returns None if no permits are available.

§Example
use async_inspect::sync::Semaphore;

let semaphore = Semaphore::new(1, "exclusive");
let result = semaphore.try_acquire();
if let Ok(permit) = result {
    println!("Got the permit!");
    drop(permit);
} else {
    println!("No permits available");
}
Source

pub fn try_acquire_many( &self, n: u32, ) -> Result<SemaphorePermit<'_>, TryAcquireError>

Try to acquire multiple permits immediately.

Source

pub fn available_permits(&self) -> usize

Get the current number of available permits.

Source

pub fn add_permits(&self, n: usize)

Add permits to the semaphore.

§Arguments
  • n - Number of permits to add
Source

pub fn close(&self)

Close the semaphore.

All pending acquire operations will fail with an error.

Source

pub fn is_closed(&self) -> bool

Check if the semaphore is closed.

Source

pub fn metrics(&self) -> LockMetrics

Get the current acquisition metrics for this semaphore.

§Example
use async_inspect::sync::Semaphore;

let semaphore = Semaphore::new(5, "pool");
// ... some operations ...
let metrics = semaphore.metrics();
println!("Acquisitions: {}", metrics.acquisitions);
println!("Contention rate: {:.1}%", metrics.contention_rate() * 100.0);
Source

pub fn reset_metrics(&self)

Reset the acquisition metrics.

Source

pub fn name(&self) -> &str

Get the name of this semaphore.

Source

pub fn resource_id(&self) -> ResourceId

Get the resource ID for deadlock detection.

Source

pub fn initial_permits(&self) -> usize

Get the initial number of permits.

Trait Implementations§

Source§

impl Debug for Semaphore

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> FutureExt for T

Source§

fn with_context(self, otel_cx: Context) -> WithContext<Self>

Attaches the provided Context to this type, returning a WithContext wrapper. Read more
Source§

fn with_current_context(self) -> WithContext<Self>

Attaches the current Context to this type, returning a WithContext wrapper. Read more
Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

impl<A, B, T> HttpServerConnExec<A, B> for T
where B: Body,