Skip to main content

RefillWaiter

Struct RefillWaiter 

Source
pub(super) struct RefillWaiter {
    granted: AtomicU64,
    waker: AtomicWaker,
}
Expand description

A refill waiter object through which the BandwidthRefiller signals a blocked acquirer.

A std::task::Waker doesn’t carry any information back to the task so this waiter carries the number of granted tokens which doubles as the “was I granted” flag.

This lives in a super::BandwidthAcquirer and is reused at every acquire which means that once the task is launched, the steady state has no extra allocation.

For sake of simplicity, there is no cancellation path and so any granted bandwidth before cancellation (drop) is forfeited.

Fields§

§granted: AtomicU64

How many tokens the refiller has granted this request with. Read by the acquirer on each poll to distinguish a grant from a spurious wakeup.

A zero means “not granted yet” where a non-zero value is the grant itself. A request is only queued for a non-zero amount.

Taken by the acquirer which then resets it to zero when it emits a permit.

§waker: AtomicWaker

The blocked acquirer’s task waker. Re-registered on every poll so it is always current, and woken by the refiller on grant.

Implementations§

Source§

impl RefillWaiter

Source

pub(super) fn new() -> Self

Constructor.

Source

fn granted(&self) -> Option<NonZero<u64>>

Return the number of tokens granted to this waiter. None means it wasn’t granted yet.

See Self::set_granted for the memory ordering.

Source

fn is_granted(&self) -> bool

Return true iff this waiter was granted permission to use the requested bandwidth.

Source

pub(super) fn prepare(&self, waker: &Waker)

Prepare this waiter for a new request with the given waker.

This must be called before the waiter is enqueued with the refiller.

Source

pub(super) fn grant(&self, granted: NonZero<u64>)

Grant a number of tokens for this waiter.

The granted value is given because it might be clamped so we record what was actually granted rather than what was asked.

This function does the atomic work in the proper order the caller doesn’t need to bother about. The concurrency handling logic is contained.

A granted value of 0 is not possible as such value indicate that the permit has not been granted yet.

Source

pub(super) fn poll_granted(&self, waker: &Waker) -> bool

Register the given waker and return true iff this waiter was granted.

Note on the function name, it doesn’t return a Poll state but this was done so the function semantic carries the intent of the context.

Source

pub(super) fn take_granted(&self) -> u64

Take the granted tokens out of this waiter leaving it to zero tokens.

This is used by the acquirer to build the permit once granted.

Source

fn set_granted(&self, val: u64)

Set atomically the given val as the granted value.

§Ordering

The grant must survive the “lost wakeup” race where the refiller grants and wakes before the acquirer has (re-)registered its waker:

    refiller:  set_granted(n)         // grant
    refiller:  waker.wake()           // no waker registered yet => wakes nobody
    acquirer:  waker.register(cx)     // register, too late for the wake above
    acquirer:  is_granted() -> ???    // must observe the grant or stuck forever

The acquirer’s re-check after waker.register must be forced to observe the grant. That happens-before is actually provided by the AtomicWaker.

Ordering::Relaxed suffices because the counter gates no other memory.

Source

fn wake(&self)

Wake the waker.

Trait Implementations§

Source§

impl Debug for RefillWaiter

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<'a, T, E> AsTaggedExplicit<'a, E> for T
where T: 'a,

Source§

fn explicit(self, class: Class, tag: u32) -> TaggedParser<'a, Explicit, Self, E>

Source§

impl<'a, T, E> AsTaggedImplicit<'a, E> for T
where T: 'a,

Source§

fn implicit( self, class: Class, constructed: bool, tag: u32, ) -> TaggedParser<'a, Implicit, Self, E>

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<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

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> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

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 = !

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