Skip to main content

BackPressure

Struct BackPressure 

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

A back-pressure semaphore plus a live-counter for observability.

The semaphore itself lives behind an Arc<BackPressureInner> so multiple BackPressure clones share the same permit pool — this is what makes the cap process-wide rather than per-instance. The optional per-call deadline lives on the clone (not inside the Arc) so two instances pulling from the same shared pool can each carry their own deadline without racing on a shared Mutex.

Implementations§

Source§

impl BackPressure

Source

pub fn new() -> Self

Construct with the default concurrency cap.

Source

pub fn with_cap(max_concurrent: usize) -> Self

Construct with an explicit concurrency cap.

Source

pub fn with_deadline_hint(self, deadline: Option<Instant>) -> Self

Attach a per-invocation deadline to this BackPressure clone.

The deadline is consulted on every acquire (both acquire and acquire_borrowed):

  • If Instant::now() >= deadline, the acquire returns BackPressureError::DeadlineElapsed without awaiting.
  • If Instant::now() >= deadline - DEADLINE_NEAR_WINDOW, the acquire returns BackPressureError::DeadlineNear — the in-flight cohort is permitted to complete but no new permits are issued.
  • Otherwise the acquire behaves exactly as before (None deadline = unchanged behaviour).

Builder method: consumes self and returns a new clone with the deadline installed. The underlying semaphore is shared via Arc so two clones that pull from the same pool can each carry their own deadline. Passing None is the documented “no deadline” knob — equivalent to a fresh BackPressure constructed via BackPressure::with_cap.

See crate::scheduler::SchedulerContext for the matching cooperative-yield query path: the executor builds both from the same Instant so the guest’s yield() verdicts and the host’s acquire decisions agree on when the deadline trips.

Source

pub fn deadline_hint(&self) -> Option<Instant>

Borrow the per-clone deadline, if any. Mirrors BackPressure::with_deadline_hint — useful for tests and observability paths that want to confirm the executor wired the deadline through.

Source

pub async fn acquire(&self) -> DispatchPermit

Acquire one permit, awaiting back-pressure if necessary.

Returns an owned permit ('static) suitable for callers that move the permit across tokio::spawn boundaries (tests, benches, any future fan-out path). Each call clones the inner Arc<Semaphore>. On the non-spawning production hot path, prefer BackPressure::acquire_borrowed which avoids that clone.

Deadline-hint-unaware: this method returns an unconditional permit and never refuses on deadline grounds. Callers that need the deadline-aware rejection path must use BackPressure::try_acquire_with_deadline or BackPressure::acquire_borrowed; this method is kept on the pre-deadline surface for tests / benches that pre-date the deadline plumbing and would otherwise need a typed-error rewrite. (The production launch_impl_async path uses acquire_borrowed, which DOES honour the deadline.)

Source

pub async fn acquire_with_deadline( &self, ) -> Result<DispatchPermit, BackPressureError>

Deadline-aware counterpart to BackPressure::acquire that returns the typed BackPressureError on rejection.

On the no-deadline path this behaves exactly like BackPressure::acquire but with the typed error surface. When a deadline is configured (via BackPressure::with_deadline_hint):

  • Past the deadline: returns Err(DeadlineElapsed).
  • Within DEADLINE_NEAR_WINDOW of the deadline: returns Err(DeadlineNear) — in-flight acquires already issued are not affected (they hold their permits to completion); only new acquires are refused, allowing the cohort to drain.
  • More than DEADLINE_NEAR_WINDOW away: behaves as BackPressure::acquire (awaits a permit).
Source

pub fn try_acquire_with_deadline( &self, ) -> Result<DispatchPermit, BackPressureError>

Non-blocking variant of BackPressure::acquire_with_deadline. Returns Err(Saturated) when no permit is immediately available and the deadline does not pre-empt the saturation path with a more specific code.

Source

pub async fn acquire_borrowed( &self, ) -> Result<BorrowedDispatchPermit<'_>, AbiError>

Acquire one permit, awaiting back-pressure if necessary.

Returns a borrowed permit whose lifetime is tied to &self. This avoids the Arc<Semaphore> clone that BackPressure::acquire performs and is the right choice for callers that hold the permit only within the current async scope (no tokio::spawn). The production launch_impl_async host-function path runs inside a wasmtime async fiber that never spawns, so it uses this variant.

§Cap-0 / saturated semantics

A cap of 0 is a “no permits, ever” sentinel: the semaphore was constructed with zero permits and none will ever be released because nothing can acquire to release. Awaiting Semaphore::acquire in that state parks the caller forever — a footgun, because guests observing back-pressure should see QuotaExceeded rather than hang. We therefore probe with try_acquire first: if it fails AND the configured cap is 0, we return AbiError::QuotaExceeded rather than awaiting. For caps > 0 we fall through to the standard async acquire (permits will eventually return as in-flight dispatches drop their permits).

Source

pub fn try_acquire(&self) -> Option<DispatchPermit>

Try to acquire a permit without awaiting. Returns None under load.

Source

pub fn active(&self) -> usize

Current number of in-flight dispatches.

Source

pub fn max_concurrent(&self) -> usize

Maximum concurrent dispatches.

Trait Implementations§

Source§

impl Clone for BackPressure

Source§

fn clone(&self) -> BackPressure

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Default for BackPressure

Source§

fn default() -> Self

Returns the “default value” for a type. 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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

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> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
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<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