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
impl Semaphore
Sourcepub fn new(permits: usize, name: impl Into<String>) -> Self
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 availablename- 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");Sourcepub async fn acquire(&self) -> Result<SemaphorePermit<'_>, AcquireError>
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 permitSourcepub async fn acquire_many(
&self,
n: u32,
) -> Result<SemaphorePermit<'_>, AcquireError>
pub async fn acquire_many( &self, n: u32, ) -> Result<SemaphorePermit<'_>, AcquireError>
Sourcepub fn try_acquire(&self) -> Result<SemaphorePermit<'_>, TryAcquireError>
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");
}Sourcepub fn try_acquire_many(
&self,
n: u32,
) -> Result<SemaphorePermit<'_>, TryAcquireError>
pub fn try_acquire_many( &self, n: u32, ) -> Result<SemaphorePermit<'_>, TryAcquireError>
Try to acquire multiple permits immediately.
Sourcepub fn available_permits(&self) -> usize
pub fn available_permits(&self) -> usize
Get the current number of available permits.
Sourcepub fn add_permits(&self, n: usize)
pub fn add_permits(&self, n: usize)
Sourcepub fn close(&self)
pub fn close(&self)
Close the semaphore.
All pending acquire operations will fail with an error.
Sourcepub fn metrics(&self) -> LockMetrics
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);Sourcepub fn reset_metrics(&self)
pub fn reset_metrics(&self)
Reset the acquisition metrics.
Sourcepub fn resource_id(&self) -> ResourceId
pub fn resource_id(&self) -> ResourceId
Get the resource ID for deadlock detection.
Sourcepub fn initial_permits(&self) -> usize
pub fn initial_permits(&self) -> usize
Get the initial number of permits.
Trait Implementations§
Auto Trait Implementations§
impl !Freeze for Semaphore
impl !RefUnwindSafe for Semaphore
impl Send for Semaphore
impl Sync for Semaphore
impl Unpin for Semaphore
impl !UnwindSafe for Semaphore
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> FutureExt for T
impl<T> FutureExt for T
Source§fn with_context(self, otel_cx: Context) -> WithContext<Self>
fn with_context(self, otel_cx: Context) -> WithContext<Self>
Source§fn with_current_context(self) -> WithContext<Self>
fn with_current_context(self) -> WithContext<Self>
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
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