pub(crate) struct Timer<R: SleepProvider> {
sleep_prov: R,
parameters: Option<PreparedParameters>,
selected_timeout: Option<Duration>,
trigger_at: Option<Instant>,
waker: Option<R::SleepFuture>,
}
Expand description
Timer that organises wakeups when channel padding should be sent
Use next()
to find when to send padding, and
note_cell_sent()
to reset the timeout when data flows.
A Timer
can be in “disabled” state, in which case next()
never completes.
Timer
must be pinned before use
(this allows us to avoid involving the allocator when we reschedule).
Fields§
§sleep_prov: R
[SleepProvider
]
parameters: Option<PreparedParameters>
Parameters controlling distribution of padding time intervals
Can be None
to mean the timing parameters are set to infinity.
selected_timeout: Option<Duration>
Gap that we intend to leave between last sent cell, and the padding
We only resample this (calculating a new random delay) after the previous timeout actually expired.
None
if the timer is disabled.
(This can be done explicitly, but also occurs on time calculation overflow.)
Invariants: this field may be Some
or None
regardless of the values
of other fields. If this field is None
then the values in trigger_at
and waker
are unspecified.
trigger_at: Option<Instant>
Absolute time at which we should send padding
None
if cells more recently sent than we were polled.
That would mean that we are currently moving data out through this channel.
The absolute timeout will need to be recalculated when the data flow pauses.
Some
means our next
has been demanded recently.
Then trigger_at
records the absolute timeout at which we should send padding,
which was calculated the first time we were polled (after data).
Invariants: the value in this field is meaningful only if selected_timeout
is Some
.
If selected_timeout
is Some
, and trigger_at
is therefore valid,
it is (obviously) no later than selected_timeout
from now.
See also waker
.
waker: Option<R::SleepFuture>
Actual waker from the SleepProvider
This is created and updated lazily, because we suspect that with some runtimes setting timeouts may be slow. Lazy updating means that with intermittent data traffic, we do not keep scheduling, descheduling, and adjusting, a wakeup time.
Invariants:
If selected_timeout
is Some
,
the time at which this waker will trigger here is never later than trigger_at
,
and never later than selected_timeout
from now.
The wakeup time here may well be earlier than trigger_at
,
and sooner than selected_timeout
from now. It may even be in the past.
When we wake up and discover this situation, we reschedule a new waker.
If selected_timeout
is None
, the value is unspecified.
We may retain a Some
in this case so that if SleepProvider
is enhanced to
support rescheduling, we can do that without making a new SleepFuture
(and without completely reorganising this the Timer
state structure.)
Implementations§
Source§impl<R: SleepProvider> Timer<R>
impl<R: SleepProvider> Timer<R>
pub(crate) fn project<'pin>( self: Pin<&'pin mut Self>, ) -> PaddingTimerProj<'pin, R>
pub(crate) fn project_ref<'pin>( self: Pin<&'pin Self>, ) -> __TimerProjectionRef<'pin, R>
Source§impl<R: SleepProvider> Timer<R>
impl<R: SleepProvider> Timer<R>
Sourcepub(crate) fn new(sleep_prov: R, parameters: Parameters) -> Result<Self>
pub(crate) fn new(sleep_prov: R, parameters: Parameters) -> Result<Self>
Create a new Timer
Sourcepub(crate) fn new_disabled(
sleep_prov: R,
parameters: Option<Parameters>,
) -> Result<Self>
pub(crate) fn new_disabled( sleep_prov: R, parameters: Option<Parameters>, ) -> Result<Self>
Create a new Timer
which starts out disabled
Sourcepub(crate) fn enable(self: &mut Pin<&mut Self>)
pub(crate) fn enable(self: &mut Pin<&mut Self>)
Enable this Timer
(If the timer was disabled, the timeout will only start to run when next()
is next polled.)
Idempotent.
Sourcepub(crate) fn reconfigure(
self: &mut Pin<&mut Self>,
parameters: &Parameters,
) -> Result<()>
pub(crate) fn reconfigure( self: &mut Pin<&mut Self>, parameters: &Parameters, ) -> Result<()>
Set this Timer
’s parameters
Will not enable or disable the timer; that must be done separately if desired.
The effect may not be immediate: if we are already in a gap between cells, that existing gap may not be adjusted. (We don’t restart the timer since that would very likely result in a gap longer than either of the configured values.)
Idempotent.
Sourcepub(crate) fn is_enabled(&self) -> bool
pub(crate) fn is_enabled(&self) -> bool
Enquire whether this Timer
is currently enabled
Sourcefn select_fresh_timeout(self: Pin<&mut Self>)
fn select_fresh_timeout(self: Pin<&mut Self>)
Select a fresh timeout (and enable, if possible)
Sourcepub(crate) fn note_cell_sent(self: &mut Pin<&mut Self>)
pub(crate) fn note_cell_sent(self: &mut Pin<&mut Self>)
Note that data has been sent (ie, reset the timeout, delaying the next padding)
Sourcefn prepare_to_sleep(
self: Pin<&mut Self>,
now: Option<Instant>,
) -> SleepInstructions<'_, R>
fn prepare_to_sleep( self: Pin<&mut Self>, now: Option<Instant>, ) -> SleepInstructions<'_, R>
Calculate when to send padding, and return a suitable waker
In the usual case returns SleepInstructions::Waker
.
Sourcepub(crate) fn next(
self: Pin<&mut Self>,
) -> impl FusedFuture<Output = Padding> + '_
pub(crate) fn next( self: Pin<&mut Self>, ) -> impl FusedFuture<Output = Padding> + '_
Wait until we should next send padding, and then return the padding message
Should be used as a low-priority branch within select_biased!
.
(next()
has to be selected on, along with other possible events, in the
main loop, so that the padding timer runs concurrently with other processing;
and it should be in a low-priority branch of select_biased!
as an optimisation:
that avoids calculating timeouts etc. until necessary,
i.e. it calculates them only when the main loop would otherwise block.)
The returned future is async-cancel-safe, but once it yields, the padding must actually be sent.
Sourceasync fn next_inner(self: Pin<&mut Self>) -> Padding
async fn next_inner(self: Pin<&mut Self>) -> Padding
Wait until we should next send padding (not FusedFuture
)
Callers wants a [FusedFuture
] because select!
needs one.
Trait Implementations§
impl<'pin, R: SleepProvider> Unpin for Timer<R>where
PinnedFieldsOf<__Timer<'pin, R>>: Unpin,
Auto Trait Implementations§
impl<R> Freeze for Timer<R>
impl<R> RefUnwindSafe for Timer<R>where
R: RefUnwindSafe,
<R as SleepProvider>::SleepFuture: RefUnwindSafe,
impl<R> Send for Timer<R>
impl<R> Sync for Timer<R>where
<R as SleepProvider>::SleepFuture: Sync,
impl<R> UnwindSafe for Timer<R>where
R: UnwindSafe,
<R as SleepProvider>::SleepFuture: UnwindSafe,
Blanket Implementations§
§impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
§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<T> Conv for T
impl<T> Conv for T
§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait>
(where Trait: Downcast
) to Box<dyn Any>
, which can then be
downcast
into Box<dyn ConcreteType>
where ConcreteType
implements Trait
.§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait>
(where Trait: Downcast
) to Rc<Any>
, which can then be further
downcast
into Rc<ConcreteType>
where ConcreteType
implements Trait
.§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &Any
’s vtable from &Trait
’s.§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &mut Any
’s vtable from &mut Trait
’s.§impl<T> DowncastSend for T
impl<T> DowncastSend for T
§impl<T> DowncastSync for T
impl<T> DowncastSync for T
§impl<T> FmtForward for T
impl<T> FmtForward for T
§fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
self
to use its Binary
implementation when Debug
-formatted.§fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
self
to use its Display
implementation when
Debug
-formatted.§fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
self
to use its LowerExp
implementation when
Debug
-formatted.§fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
self
to use its LowerHex
implementation when
Debug
-formatted.§fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
self
to use its Octal
implementation when Debug
-formatted.§fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
self
to use its Pointer
implementation when
Debug
-formatted.§fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
self
to use its UpperExp
implementation when
Debug
-formatted.§fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
self
to use its UpperHex
implementation when
Debug
-formatted.§fn fmt_list(self) -> FmtList<Self>where
&'a Self: for<'a> IntoIterator,
fn fmt_list(self) -> FmtList<Self>where
&'a Self: for<'a> IntoIterator,
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§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§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
self
and passes that borrow into the pipe function. Read more§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
self
and passes that borrow into the pipe function. Read more§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R,
) -> R
fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
self
, then passes self.as_ref()
into the pipe function.§fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
self
, then passes self.as_mut()
into the pipe
function.§fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
self
, then passes self.deref()
into the pipe function.§impl<T> Tap for T
impl<T> Tap for T
§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
Borrow<B>
of a value. Read more§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
BorrowMut<B>
of a value. Read more§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
AsRef<R>
view of a value. Read more§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
AsMut<R>
view of a value. Read more§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
Deref::Target
of a value. Read more§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
Deref::Target
of a value. Read more§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
.tap()
only in debug builds, and is erased in release builds.§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
.tap_mut()
only in debug builds, and is erased in release
builds.§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
.tap_borrow()
only in debug builds, and is erased in release
builds.§fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
.tap_borrow_mut()
only in debug builds, and is erased in release
builds.§fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
.tap_ref()
only in debug builds, and is erased in release
builds.§fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
.tap_ref_mut()
only in debug builds, and is erased in release
builds.§fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
.tap_deref()
only in debug builds, and is erased in release
builds.