event/TimerWheel: add `empty` flag to optimize a common case

This commit is contained in:
Max Kellermann 2021-02-17 19:49:00 +01:00
parent ce6afe9379
commit 0924b63e10
2 changed files with 18 additions and 1 deletions

View File

@ -54,6 +54,8 @@ TimerWheel::Insert(CoarseTimerEvent &t) noexcept
const auto due = std::max(t.GetDue(), last_time);
buckets[BucketIndexAt(due)].push_back(t);
empty = false;
}
void
@ -99,10 +101,15 @@ TimerWheel::GetNextDue(const std::size_t bucket_index,
inline Event::Duration
TimerWheel::GetSleep(Event::TimePoint now) const noexcept
{
if (empty)
return Event::Duration(-1);
auto t = GetNextDue(BucketIndexAt(now), GetBucketStartTime(now));
assert(t > now);
if (t == Event::TimePoint::max())
if (t == Event::TimePoint::max()) {
empty = true;
return Event::Duration(-1);
}
return t - now;
}

View File

@ -72,6 +72,16 @@ class TimerWheel final {
*/
Event::TimePoint last_time{};
/**
* If this flag is true, then all buckets are guaranteed to be
* empty. If it is false, the buckets may or may not be
* empty; if so, the next full scan will set it back to true.
*
* This field is "mutable" so the "const" method GetSleep()
* can update it.
*/
mutable bool empty = true;
public:
TimerWheel() noexcept;
~TimerWheel() noexcept;