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: AtomicU64How 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: AtomicWakerThe 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
impl RefillWaiter
Sourcefn granted(&self) -> Option<NonZero<u64>>
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.
Sourcefn is_granted(&self) -> bool
fn is_granted(&self) -> bool
Return true iff this waiter was granted permission to use the requested bandwidth.
Sourcepub(super) fn prepare(&self, waker: &Waker)
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.
Sourcepub(super) fn grant(&self, granted: NonZero<u64>)
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.
Sourcepub(super) fn poll_granted(&self, waker: &Waker) -> bool
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.
Sourcepub(super) fn take_granted(&self) -> u64
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.
Sourcefn set_granted(&self, val: u64)
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 foreverThe 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.
Trait Implementations§
Auto Trait Implementations§
impl !Freeze for RefillWaiter
impl !RefUnwindSafe for RefillWaiter
impl Send for RefillWaiter
impl Sync for RefillWaiter
impl Unpin for RefillWaiter
impl UnsafeUnpin for RefillWaiter
impl UnwindSafe for RefillWaiter
Blanket Implementations§
Source§impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
Source§impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
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
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
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