pub enum MissedTickBehavior {
    Burst,
    Delay,
    Skip,
}
Expand description

Defines the behavior of an Interval when it misses a tick.

Sometimes, an Interval’s tick is missed. For example, consider the following:

use tokio::time::{self, Duration};

#[tokio::main]
async fn main() {
    // ticks every 2 milliseconds
    let mut interval = time::interval(Duration::from_millis(2));
    for _ in 0..5 {
        interval.tick().await;
        // if this takes more than 2 milliseconds, a tick will be delayed
        task_that_takes_one_to_three_millis().await;
    }
}

Generally, a tick is missed if too much time is spent without calling Interval::tick().

By default, when a tick is missed, Interval fires ticks as quickly as it can until it is “caught up” in time to where it should be. MissedTickBehavior can be used to specify a different behavior for Interval to exhibit. Each variant represents a different strategy.

Note that because the executor cannot guarantee exact precision with timers, these strategies will only apply when the delay is greater than 5 milliseconds.

Variants

Burst

Ticks as fast as possible until caught up.

When this strategy is used, Interval schedules ticks “normally” (the same as it would have if the ticks hadn’t been delayed), which results in it firing ticks as fast as possible until it is caught up in time to where it should be. Unlike Delay and Skip, the ticks yielded when Burst is used (the Instants that tick yields) aren’t different than they would have been if a tick had not been missed. Like Skip, and unlike Delay, the ticks may be shortened.

This looks something like this:

Expected ticks: |     1     |     2     |     3     |     4     |     5     |     6     |
Actual ticks:   | work -----|          delay          | work | work | work -| work -----|

In code:

use tokio::time::{interval, Duration};

let mut interval = interval(Duration::from_millis(50));

// First tick resolves immediately after creation
interval.tick().await;

task_that_takes_200_millis().await;
// The `Interval` has missed a tick

// Since we have exceeded our timeout, this will resolve immediately
interval.tick().await;

// Since we are more than 100ms after the start of `interval`, this will
// also resolve immediately.
interval.tick().await;

// Also resolves immediately, because it was supposed to resolve at
// 150ms after the start of `interval`
interval.tick().await;

// Resolves immediately
interval.tick().await;

// Since we have gotten to 200ms after the start of `interval`, this
// will resolve after 50ms
interval.tick().await;

This is the default behavior when Interval is created with interval and interval_at.

Delay

Tick at multiples of period from when tick was called, rather than from start.

When this strategy is used and Interval has missed a tick, instead of scheduling ticks to fire at multiples of period from start (the time when the first tick was fired), it schedules all future ticks to happen at a regular period from the point when tick was called. Unlike Burst and Skip, ticks are not shortened, and they aren’t guaranteed to happen at a multiple of period from start any longer.

This looks something like this:

Expected ticks: |     1     |     2     |     3     |     4     |     5     |     6     |
Actual ticks:   | work -----|          delay          | work -----| work -----| work -----|

In code:

use tokio::time::{interval, Duration, MissedTickBehavior};

let mut interval = interval(Duration::from_millis(50));
interval.set_missed_tick_behavior(MissedTickBehavior::Delay);

task_that_takes_more_than_50_millis().await;
// The `Interval` has missed a tick

// Since we have exceeded our timeout, this will resolve immediately
interval.tick().await;

// But this one, rather than also resolving immediately, as might happen
// with the `Burst` or `Skip` behaviors, will not resolve until
// 50ms after the call to `tick` up above. That is, in `tick`, when we
// recognize that we missed a tick, we schedule the next tick to happen
// 50ms (or whatever the `period` is) from right then, not from when
// were were *supposed* to tick
interval.tick().await;

Skip

Skips missed ticks and tick on the next multiple of period from start.

When this strategy is used, Interval schedules the next tick to fire at the next-closest tick that is a multiple of period away from start (the point where Interval first ticked). Like Burst, all ticks remain multiples of period away from start, but unlike Burst, the ticks may not be one multiple of period away from the last tick. Like Delay, the ticks are no longer the same as they would have been if ticks had not been missed, but unlike Delay, and like Burst, the ticks may be shortened to be less than one period away from each other.

This looks something like this:

Expected ticks: |     1     |     2     |     3     |     4     |     5     |     6     |
Actual ticks:   | work -----|          delay          | work ---| work -----| work -----|

In code:

use tokio::time::{interval, Duration, MissedTickBehavior};

let mut interval = interval(Duration::from_millis(50));
interval.set_missed_tick_behavior(MissedTickBehavior::Skip);

task_that_takes_75_millis().await;
// The `Interval` has missed a tick

// Since we have exceeded our timeout, this will resolve immediately
interval.tick().await;

// This one will resolve after 25ms, 100ms after the start of
// `interval`, which is the closest multiple of `period` from the start
// of `interval` after the call to `tick` up above.
interval.tick().await;

Trait Implementations

Returns a copy of the value. Read more

Performs copy-assignment from source. Read more

Formats the value using the given formatter. Read more

Returns MissedTickBehavior::Burst.

For most usecases, the Burst strategy is what is desired. Additionally, to preserve backwards compatibility, the Burst strategy must be the default. For these reasons, MissedTickBehavior::Burst is the default for MissedTickBehavior. See Burst for more details.

This method tests for self and other values to be equal, and is used by ==. Read more

This method tests for !=.

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

Immutably borrows from an owned value. Read more

Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

The resulting type after obtaining ownership.

Creates owned data from borrowed data, usually by cloning. Read more

🔬 This is a nightly-only experimental API. (toowned_clone_into)

Uses borrowed data to replace owned data, usually by cloning. Read more

The type returned in the event of a conversion error.

Performs the conversion.

The type returned in the event of a conversion error.

Performs the conversion.