Skip to main content

DebouncedTimeout

Struct DebouncedTimeout 

Source
pub struct DebouncedTimeout<T> { /* private fields */ }
Expand description

A Stop wrapper that debounces the Instant::now() call.

The first two checks read the clock, and the interval between them sets N; after that, check() reads the clock every N calls, where N is chosen so clock reads happen approximately once per target_interval, and is at most 64 (see Deadline precision).

Adaptation behavior:

  • If calls slow down (longer between checks), increases check frequency at the next clock read, to avoid missing the deadline.
  • If calls speed up (shorter between checks), gradually decreases check frequency to avoid over-checking.
  • clear_calibration starts over from two checks, for code that knows its checks are about to change pace, such as at the start of a slower stage.

§Deadline precision

It reads the clock about once per target interval (default 100μs), and at least every 64 checks. While checks arrive at a steady rate it stops at most about one target interval late, or one check late when checks come further apart than that. It learns that checks have slowed down only at its next clock read, so after a sudden slowdown (a library moving on to a slower stage, say) it can stop up to 64 of the slower checks late: 64 ms if they then come once a millisecond. WithTimeout stops at most one check late. Where the code holding the timeout knows the pace is about to change, clear_calibration makes it notice within two checks. If you need sub-100μs precision, either lower the target with with_target_interval or use WithTimeout directly.

§When to Use

Prefer DebouncedTimeout over WithTimeout when the Stop implementation crosses an API boundary — the caller adds the deadline, but the library controls check frequency. This avoids coupling timeout overhead to the library’s internal loop structure.

In tight loops (sub-microsecond between checks), the savings are ~10x. In codec workloads (~4KB between checks), both types are equivalent because the real work dwarfs the clock read.

§Example

use almost_enough::{StopSource, Stop};
use almost_enough::time::DebouncedTimeout;
use std::time::Duration;

let source = StopSource::new();
let stop = DebouncedTimeout::new(source.as_ref(), Duration::from_millis(100));

// Fast loop — most check() calls skip the clock read
let mut i = 0u64;
while !stop.should_stop() {
    i += 1;
    if i > 1_000_000 { break; }
}

Implementations§

Source§

impl<T: Stop> DebouncedTimeout<T>

Source

pub fn new(inner: T, duration: Duration) -> Self

Create a new debounced timeout with the default target interval (100μs).

The deadline is calculated as Instant::now() + duration. Durations longer than ~584 years are clamped to u64::MAX nanoseconds.

Source

pub fn with_deadline(inner: T, deadline: Instant) -> Self

Create a debounced timeout with an absolute deadline.

If the deadline is in the past, the first clock read will trigger StopReason::TimedOut.

Source

pub fn with_target_interval(self, interval: Duration) -> Self

Set the target interval between clock reads.

Smaller values check the clock more often (more responsive but more overhead). Larger values check less often (less overhead but may overshoot the deadline by up to this amount while checks arrive steadily). The clock is read at least every 64 checks regardless.

Default: 100μs (0.1ms).

Source

pub fn deadline(&self) -> Instant

Get the deadline as an Instant.

Source

pub fn remaining(&self) -> Duration

Get the remaining time until deadline.

Returns Duration::ZERO if the deadline has passed.

Source

pub fn inner(&self) -> &T

Get a reference to the inner stop.

Source

pub fn into_inner(self) -> T

Unwrap and return the inner stop.

Source

pub fn checks_per_clock_read(&self) -> u32

Current number of check() calls between clock reads.

Starts at 1 (every call), is set from the interval between the first two checks, and then adapts as the call rate is measured, up to 64. Useful for diagnostics and testing.

Source

pub fn clear_calibration(&self)

Forget the measured check rate: the next two checks read the clock, and the interval between them sets how often it is read after that.

Call it where checks are about to change pace, such as when a library moves on to a slower stage. Without it, a slowdown is noticed at the next scheduled clock read, up to 64 of the slower checks later.

Source§

impl<T: Stop> DebouncedTimeout<T>

Source

pub fn tighten(self, duration: Duration) -> Self

Add another timeout, taking the tighter of the two deadlines.

Resets calibration state since the new deadline may require a different check frequency.

Source

pub fn tighten_deadline(self, deadline: Instant) -> Self

Add another deadline, taking the earlier of the two.

Resets calibration state since the new deadline may require a different check frequency.

Trait Implementations§

Source§

impl<T: Clone + Stop> Clone for DebouncedTimeout<T>

Source§

fn clone(&self) -> Self

Clone resets calibration state — each clone starts fresh.

1.0.0 (const: unstable) · Source§

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

Performs copy-assignment from source. Read more
Source§

impl<T: Debug> Debug for DebouncedTimeout<T>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<T: Stop> Stop for DebouncedTimeout<T>

Source§

fn check(&self) -> Result<(), StopReason>

Check if the operation should stop. Read more
Source§

fn should_stop(&self) -> bool

Returns true if the operation should stop. Read more
Source§

fn may_stop(&self) -> bool

Returns true if this stop can ever signal a stop. Read more

Auto Trait Implementations§

§

impl<T> !Freeze for DebouncedTimeout<T>

§

impl<T> RefUnwindSafe for DebouncedTimeout<T>
where T: RefUnwindSafe,

§

impl<T> Send for DebouncedTimeout<T>
where T: Send,

§

impl<T> Sync for DebouncedTimeout<T>
where T: Sync,

§

impl<T> Unpin for DebouncedTimeout<T>
where T: Unpin,

§

impl<T> UnsafeUnpin for DebouncedTimeout<T>
where T: UnsafeUnpin,

§

impl<T> UnwindSafe for DebouncedTimeout<T>
where T: UnwindSafe,

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> CloneStop for T
where T: Stop + Clone + 'static,

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> DebouncedTimeoutExt for T
where T: Stop,

Source§

fn with_debounced_timeout(self, duration: Duration) -> DebouncedTimeout<Self>

Add a debounced timeout to this stop. Read more
Source§

fn with_debounced_deadline(self, deadline: Instant) -> DebouncedTimeout<Self>

Add a debounced timeout with an absolute deadline.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

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> StopExt for T
where T: Stop,

Source§

fn or<S: Stop>(self, other: S) -> OrStop<Self, S>

Combine this stop with another, stopping if either stops. Read more
Source§

fn into_boxed(self) -> BoxedStop
where Self: 'static,

👎Deprecated since 0.4.5:

use into_token(), whose StopToken checks the same way and is Clone

Convert this stop into a BoxedStop. Deprecated: use into_token(), whose StopToken checks the same way and is Clone.
Source§

fn into_token(self) -> StopToken
where Self: 'static,

Convert this stop into a shared, cloneable StopToken. Read more
Source§

fn child(&self) -> ChildStopper
where Self: Clone + 'static,

Create a child stop that inherits cancellation from this stop. Read more
Source§

impl<T> TimeoutExt for T
where T: Stop,

Source§

fn with_timeout(self, duration: Duration) -> WithTimeout<Self>

Add a timeout to this stop. Read more
Source§

fn with_deadline(self, deadline: Instant) -> WithTimeout<Self>

Add an absolute deadline to this stop. 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 = !

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.