Skip to content

Commit

Permalink
feat(timer): Allow limiting the work done by dispatch
Browse files Browse the repository at this point in the history
Sometimes it is required that TimerQueue::dispatch finishes fast in a
bounded amount of time while still making progress on the queued timers.
In which case, you want dispatch to process a small number of queued
timers and then return back to caller.

Furthermore, limit the work done by low priority timer queue to just 1
in the reactor. This prevents too much time being taken by low priority
timers if there are a lot of them eligible to be dispatched.
They are low priority timers, so its ok if they are delayed by a little
bit of time.

SDB-8174
  • Loading branch information
bnbajwa committed Nov 7, 2024
1 parent 03a003b commit fbbbdc3
Show file tree
Hide file tree
Showing 3 changed files with 9 additions and 8 deletions.
2 changes: 1 addition & 1 deletion toolbox/io/Reactor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ int Reactor::poll(CyclTime now, Duration timeout)
work += dispatch(now, buf, n);
// Low priority timers are only dispatched during empty cycles.
if (work == 0) {
work += tqs_[Low].dispatch(now);
work += tqs_[Low].dispatch(now, 1);
}
// End of cycle hooks.
if (work > 0) {
Expand Down
12 changes: 6 additions & 6 deletions toolbox/io/Timer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,25 +76,25 @@ Timer TimerQueue::insert(MonoTime expiry, Duration interval, TimerSlot slot)
return tmr;
}

int TimerQueue::dispatch(CyclTime now)
int TimerQueue::dispatch(CyclTime now, int max_work)
{
int work{};
while (!heap_.empty()) {

int timers_processed{0};
for (int i = 0; (i < max_work) && (!heap_.empty()); i++) {
// If not pending, then must have been cancelled.
if (!heap_.front().pending()) {
pop();
--cancelled_;
assert(cancelled_ >= 0);
} else if (heap_.front().expiry() <= now.mono_time()) {
expire(now);
++work;
++timers_processed;
} else {
break;
}
}

gc();
return work;
return timers_processed;
}

Timer TimerQueue::allocate(MonoTime expiry, Duration interval, TimerSlot slot)
Expand Down
3 changes: 2 additions & 1 deletion toolbox/io/Timer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#ifndef TOOLBOX_IO_TIMER_HPP
#define TOOLBOX_IO_TIMER_HPP

#include <limits>
#include <toolbox/sys/Time.hpp>
#include <toolbox/util/Slot.hpp>

Expand Down Expand Up @@ -167,7 +168,7 @@ class TOOLBOX_API TimerQueue {
}
// clang-format on

int dispatch(CyclTime now);
int dispatch(CyclTime now, int max_work = std::numeric_limits<int>::max());

private:
Timer allocate(MonoTime expiry, Duration interval, TimerSlot slot);
Expand Down

0 comments on commit fbbbdc3

Please sign in to comment.