ITADN

maitake timer should support rescheduling sleeps

#556Openhawkw 创建于 2025-10-17
kind/enhancementcrate/maitake
H
hawkwcommented
Currently, using `maitake`'s `time` module, if you want to implement a repeating periodic action on a scheduled interval, you would write something like this: ```rust let interval = maitake::time::Duration::from_secs(5); // or whatever loop { maitake::time::sleep(interval).await; do_the_thing().await; } ``` This _works_ fine, but it has a bit of extra overhead. Creating a new `sleep` future locks the timer wheel, so we have to do that every time we start waiting again. When the sleep completes, it's removed from the wheel. To make the periodic timer use case more efficient, Tokio provides [the `tokio::time::Interval` type](https://docs.rs/tokio/latest/tokio/time/struct.Interval.html) (and the `tokio::time::{interval, interval_at}` functions). This is similar to a `sleep`, except that instead of _removing_ the entry from the timer wheel when it completes, the wheel automatically reschedules it to fire again the next time the period has elapsed. This avoids having to re-lock the wheel the next time the code that implements a periodic action wants to create a new sleep. The API for this allows the user code to wait on a `tick()` future returned by the `Interval` type, rather than consuming it: ```rust let mut interval = maitake::time::interval(Duration::from_secs(5)); // or whatever loop { interval.tick().await; do_the_thing().await; } ``` It_also_ makes the period a bit more accurate, since the next period starts as soon as the timer wheel entry is _woken_, rather than after the periodic action runs and the periodic task wishes to wait for the next period to elapse. In the above examples, if `do_the_thing()` took a long time to complete, or sometimes yields for a long time waiting on some external wakeup, the sleep based approach is actually running the action exactly every 5 seconds, but every 5 + (how long it takes for `do_the_thing()` to return) seconds. This makes the period a bit sloppier than it would be if the timer was automatically rescheduled as soon as the timer wheel wakes it up. If we supported the internal mechanisms to re-schedule a (potentially) completed timer wheel entry, we would also be able to implement a function for resetting a `Sleep` to fire at an arbitrary duration, like [`tokio::time::Sleep::reset()`](https://docs.rs/tokio/latest/tokio/time/struct.Sleep.html#method.reset). While this interface wouldn't be a replacement for an automatically-reset `Interval` (as it would still lock the wheel every time the timer wheel entry is reset _through the `Sleep` type_), it's a nice interface to have for some use cases, like `select!`ing over a sleep and a bunch of other futures in a loop. Sometimes, user code may wish to reset the sleep to be selected over in another iteration of a loop if a _different_ future completed first, such as to reset a timeout. An API for this is a bit less annoying than one where you have to replace the `Sleep` with a whole new one. And, it's a bit more efficient, since replacing a `Sleep` that hasn't completed with a new one locks the wheel _twice_ --- once to create the new `Sleep` and again to drop the old one. The `reset()` API never drops a sleep, so it's only one lock.
1 条评论