Skip to main content

StopWatcher

Struct StopWatcher 

Source
struct StopWatcher {
    watching: Option<Pin<Box<dyn Future<Output = Result<(), TransportError>> + Send>>>,
    armed: bool,
}
Expand description

A destination-side STOP_SENDING watcher, hoisted once per forwarded stream and used as a fourth tokio::select! branch.

§Why it is hoisted

tokio::select! drops and rebuilds every branch future each time round the loop. Rebuilding SendStream::stopped() takes quinn’s connection state lock and inserts into a per-connection map (quinn-0.11.9/src/send_stream.rs:258-263), which is per-wake work on loops documented as doing none. So the future is built once, lives here across iterations, and Self::watch borrows it rather than moving it — a select! iteration that cancels this branch therefore loses nothing and resumes the same future next time round.

§Why it is fused

Building it once means it can only resolve once: polling a completed future panics with “async fn resumed after completion”. Self::watch clears the slot the instant the future returns, which both disables the branch (through Self::is_watching) and makes a re-poll structurally unreachable. The fuse is not belt and braces — without it the very next select! iteration panics inside the forwarding task.

Self::armed is what keeps the fuse one-way: a retired watcher has an empty slot, and without the flag the next Self::arm would rebuild it.

§Cost

One Box::pin per forwarded stream, allocated at the first select! iteration and never again. Per stream, never per object.

Fields§

§watching: Option<Pin<Box<dyn Future<Output = Result<(), TransportError>> + Send>>>

The hoisted stopped() future. None before Self::arm, and again once it has resolved or Self::retire was called.

§armed: bool

Set by the first Self::arm, so a retired watcher stays retired.

Implementations§

Source§

impl StopWatcher

Source

fn new() -> Self

An unarmed watcher. Allocates nothing.

Source

fn arm(&mut self, send: &SendStream)

Build the watcher over send, once. Called from the top of each pipe’s loop rather than before it, so pipe_data_passthrough — whose contract is a stack buffer and a write — allocates on its first select! iteration and not at function entry. Idempotent: a second call is a no-op, and a call after Self::retire does not re-arm.

Source

fn is_watching(&self) -> bool

Whether the select! branch should be enabled this iteration.

Source

fn retire(&mut self)

Drop the watcher without polling it again.

Called before every local send.reset: quinn keeps no stopped-notification for a stream it has locally reset, so a watcher held across a reset stays pending until the connection ends (see SendStream::stopped’s own docs). Every reset site returns from its pipe immediately afterwards, so this is about saying what the code means as much as about the residue.

Source

async fn watch(&mut self) -> Result<(), TransportError>

Resolve when the destination stops being useful — then never again.

Stays pending forever once retired, so an enabled-but-retired branch cannot spin; the if guard is the fast path and this is the backstop.

Cancellation-safe: the fuse below is reached only on completion, so a select! iteration that drops this future mid-poll leaves the hoisted future exactly where it was.

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.

§

impl<T> Instrument for T

§

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

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

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, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

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

fn try_from(value: U) -> Result<T, !>

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.
§

impl<T> WithSubscriber for T

§

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
§

fn with_current_subscriber(self) -> WithDispatch<Self>

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