time: return the earliest key from DelayQueue::peek (#8402)

This commit is contained in:
Dylan Pulver
2026-09-04 14:29:10 +02:00
committed by GitHub
parent 103d29f808
commit bb5a0fce23
5 changed files with 70 additions and 7 deletions
+22 -1
View File
@@ -951,7 +951,7 @@ impl<T> DelayQueue<T> {
pub fn peek(&self) -> Option<Key> {
use self::wheel::Stack;
self.expired.peek().or_else(|| self.wheel.peek())
self.expired.peek().or_else(|| self.wheel.peek(&self.slab))
}
/// Returns the next time to poll as determined by the wheel.
@@ -1260,6 +1260,27 @@ impl<T> wheel::Stack for Stack<T> {
self.head
}
fn peek_earliest(&self, store: &Self::Store) -> Option<Self::Owned> {
let head = self.head?;
let mut earliest = (head, store[head].when);
let mut curr = store[head].next;
while let Some(key) = curr {
let data = &store[key];
// The comparison is strict so that the first entry seen wins a tie,
// which agrees with `pop` when every entry in the slot shares a
// deadline.
if data.when < earliest.1 {
earliest = (key, data.when);
}
curr = data.next;
}
Some(earliest.0)
}
#[track_caller]
fn remove(&mut self, item: &Self::Borrowed, store: &mut Self::Store) {
let key = *item;
+2 -2
View File
@@ -148,8 +148,8 @@ impl<T: Stack> Level<T> {
ret
}
pub(crate) fn peek_entry_slot(&self, slot: usize) -> Option<T::Owned> {
self.slot[slot].peek()
pub(crate) fn peek_entry_slot(&self, slot: usize, store: &T::Store) -> Option<T::Owned> {
self.slot[slot].peek_earliest(store)
}
}
+4 -4
View File
@@ -140,9 +140,9 @@ where
}
/// Next key that will expire
pub(crate) fn peek(&self) -> Option<T::Owned> {
pub(crate) fn peek(&self, store: &T::Store) -> Option<T::Owned> {
self.next_expiration()
.and_then(|expiration| self.peek_entry(&expiration))
.and_then(|expiration| self.peek_entry(&expiration, store))
}
/// Advances the timer up to the instant represented by `now`.
@@ -250,8 +250,8 @@ where
self.levels[expiration.level].pop_entry_slot(expiration.slot, store)
}
fn peek_entry(&self, expiration: &Expiration) -> Option<T::Owned> {
self.levels[expiration.level].peek_entry_slot(expiration.slot)
fn peek_entry(&self, expiration: &Expiration, store: &T::Store) -> Option<T::Owned> {
self.levels[expiration.level].peek_entry_slot(expiration.slot, store)
}
fn level_for(&self, when: u64) -> usize {
+7
View File
@@ -25,6 +25,13 @@ pub(crate) trait Stack: Default {
/// Peek into the stack.
fn peek(&self) -> Option<Self::Owned>;
/// Peek at the item in the stack with the earliest deadline.
///
/// Unlike `peek`, this does not have to agree with `pop`: a slot in a level
/// above zero spans a range of deadlines, so its entries are only ordered
/// once they cascade down.
fn peek_earliest(&self, store: &Self::Store) -> Option<Self::Owned>;
fn remove(&mut self, item: &Self::Borrowed, store: &mut Self::Store);
fn when(item: &Self::Borrowed, store: &Self::Store) -> u64;